Home > database >  SQL query to check if there are records in the database of 6 consecutive 'Sundays'
SQL query to check if there are records in the database of 6 consecutive 'Sundays'

Time:11-24

I need to build a query to check if there are records in the database of 6 consecutive 'Sundays'

SELECT DISTINCT ST1.DATAPU, ST1.NUMCAD, TO_CHAR(ST1.DATAPU, 'DAY') AS DIA
  FROM SENIOR.R066SIT ST1
 WHERE ST1.DATAPU BETWEEN '01/01/22' AND '23/11/22'
   AND ST1.NUMCAD = 10
   AND TO_CHAR(ST1.DATAPU, 'FMDAY') = 'DOMINGO' -->which is SUNDAY in English
 ORDER BY ST1.DATAPU ASC

With this query above, I get the result of the records as shown in the image below

enter image description here

CodePudding user response:

From Oracle 12, you can use MATCH_RECOGNIZE to perform row-by-row pattern analysis:

SELECT *
FROM   (
  SELECT DISTINCT
         TRUNC(DATAPU) AS datapu,
         NUMCAD,
         TO_CHAR(DATAPU,'DAY') AS DIA
  FROM   SENIOR.R066SIT
  WHERE  DATAPU BETWEEN DATE '2022-01-01' AND DATE '2022-11-23'
  AND    NUMCAD = 10
  AND    TRUNC(DATAPU) - TRUNC(DATAPU, 'IW') = 6 -- Sunday
)
MATCH_RECOGNIZE(
  ORDER BY datapu
  ALL ROWS PER MATCH
  PATTERN (first_week consecutive_week{5,})
  DEFINE
    consecutive_week AS PREV(datapu)   INTERVAL '7' DAY = datapu
)

Which, for the sample data:

CREATE TABLE senior.r066sit(numcad, datapu) AS
SELECT 10, DATE '2022-01-01'   LEVEL - 1 FROM DUAL CONNECT BY LEVEL <= 5*7
UNION ALL
SELECT 10, DATE '2022-04-01'   LEVEL - 1 FROM DUAL CONNECT BY LEVEL <= 7*7
UNION ALL
SELECT 10, DATE '2022-08-01'   LEVEL - 1 FROM DUAL CONNECT BY LEVEL <= 7*7;

Outputs:

DATAPU NUMCAD DIA
2022-04-03 00:00:00 10 SUNDAY
2022-04-10 00:00:00 10 SUNDAY
2022-04-17 00:00:00 10 SUNDAY
2022-04-24 00:00:00 10 SUNDAY
2022-05-01 00:00:00 10 SUNDAY
2022-05-08 00:00:00 10 SUNDAY
2022-05-15 00:00:00 10 SUNDAY
2022-08-07 00:00:00 10 SUNDAY
2022-08-14 00:00:00 10 SUNDAY
2022-08-21 00:00:00 10 SUNDAY
2022-08-28 00:00:00 10 SUNDAY
2022-09-04 00:00:00 10 SUNDAY
2022-09-11 00:00:00 10 SUNDAY
2022-09-18 00:00:00 10 SUNDAY

Before Oracle 12, you can use multiple analytic functions in nested sub-queries:

SELECT datapu, numcad,
       TO_CHAR(datapu, 'fmDAY') AS dia
FROM   (
  SELECT datapu, numcad,
         COUNT(*) OVER (PARTITION BY grp) AS grp_size
  FROM   (  
    SELECT datapu, numcad,
           SUM(consecutive) OVER (ORDER BY datapu) AS grp
    FROM   (
      SELECT datapu, numcad,
             CASE datapu - LAG(datapu) OVER (ORDER BY datapu)
             WHEN 7
             THEN 0
             ELSE 1
             END AS consecutive
      FROM   (
        SELECT DISTINCT
               TRUNC(DATAPU) AS datapu,
               NUMCAD
        FROM   SENIOR.R066SIT
        WHERE  DATAPU BETWEEN DATE '2022-01-01' AND DATE '2022-11-23'
        AND    NUMCAD = 10
        AND    TRUNC(DATAPU) - TRUNC(DATAPU, 'IW') = 6 -- Sunday
      )
    )
  )
)
WHERE  grp_size >= 6;

fiddle

  • Related