Что я могу использовать в запросе SQL, чтобы помочь мне определить, почему мой запрос не возвращает результатов данных - PullRequest
0 голосов
/ 16 января 2019

Может ли кто-нибудь помочь мне в устранении неполадок моего запроса SQL, чтобы выяснить, почему он не возвращает никаких результатов, только псевдонимы столбцов?

Я разбил его на части, и все разделы, которые, очевидно, группируются, возвращают ожидаемые данные по отдельности. Спасибо за любое руководство / помощь заранее. Ниже мой сценарий:

...

DECLARE @u_cnt INT;
DECLARE @f_yr DATE;
DECLARE @qrt VARCHAR(3);
DECLARE @dnum VARCHAR(5);


SET @u_cnt = 10000;
SET @f_yr = '2002-05-20';
SET @qrt = 'Q2';
SET @dnum = '43234';




SELECT c.GroupLabel AS ORG_Code,
   CONVERT (VARCHAR(7), FORMAT((CONVERT(DATE, c.changedate)), 'MM-yyyy')) AS [MONTH],
   COUNT(DISTINCT CASE s.TestType 
         WHEN 'IR' THEN c.changedate
              ELSE NULL END) AS TEST_DAYS,
   COUNT(DISTINCT c.changedate) AS ALLDAYS,
   COUNT(s.Id) AS total,
   (CASE WHEN (@u_cnt IS NULL) THEN -1 
         ELSE @u_cnt
         END) AS board_cnt,
   FORMAT((COUNT(s.Id) / CASE
                                WHEN (@u_cnt IS NULL) THEN -1 
                                ELSE @u_cnt
                                END), 'P0') AS pct_tested_text,

   CASE WHEN 100 * (COUNT(s.Id) / CASE 
                                   WHEN (@u_cnt IS NULL) THEN -1 
                                   ELSE @u_cnt 
                                   END) >= 15 
               AND (COUNT(DISTINCT CASE s.TestType
                          WHEN 'IR' THEN c.changedate
                          ELSE NULL END)) >= 4  
   THEN 'Yes'
   ELSE 'NO' END 
FROM cforms c 
INNER JOIN spitems sp
ON c.Id = s.FormId
WHERE c.Group = 'HR'
AND c.bFlag IS NULL
AND s.Report IN ('P', 'N')
AND CONVERT(VARCHAR(6), c.changedate, 112) IN
       (SELECT
            CASE 
                WHEN f.Quarter = 'Q1' THEN CONVERT(VARCHAR(4), YEAR(@f_yr) - 1) + f.FyMonthNumber
                WHEN f.Quarter = 'ALL' AND f.FyMonth IN ('OCT', 'NOV', 'DEC') THEN CONVERT(VARCHAR(4), YEAR(@f_yr) - 1, 112) + f.FyM
                ELSE CONVERT(VARCHAR(4), YEAR(@f_yr), 112) + f.FyM 
            END AS FY_MONTH
        FROM fis f
        WHERE f.Quarter = @qrt)
AND c.GroupLabel = 'Hr' + @dnum
GROUP BY c.GroupLabel, FORMAT((CONVERT(DATE, c.changedate)), 'MM-yyyy')
ORDER BY 1, FORMAT((CONVERT(DATE, c.changedate)), 'MM-yyyy');

Ответы [ 6 ]

0 голосов
/ 23 января 2019

JOIN или / и предложения WHERE могут быть причиной. Следующий основной метод дедукции - выяснить, какая часть запроса дает такой результат:

Во-первых, удалите все предложения WHERE и проверьте, может ли текущий JOIN возвращать строки, установив WHERE следующим образом:

WHERE 1 = 1
--AND c.Group = 'HR'
--AND c.bFlag IS NULL
--AND s.Report IN ('P', 'N')
--AND CONVERT(VARCHAR(6), c.changedate, 112) IN
--       (SELECT
--            CASE 
--                WHEN f.Quarter = 'Q1' THEN CONVERT(VARCHAR(4), YEAR(@f_yr) - 1) + f.FyMonthNumber
--                WHEN f.Quarter = 'ALL' AND f.FyMonth IN ('OCT', 'NOV', 'DEC') THEN CONVERT(VARCHAR(4), YEAR(@f_yr) - 1, 112) + f.FyM
--                ELSE CONVERT(VARCHAR(4), YEAR(@f_yr), 112) + f.FyM 
--            END AS FY_MONTH
--        FROM fis f
--        WHERE f.Quarter = @qrt)
--AND c.GroupLabel = 'Hr' + @dnum

Затем, раскомментируйте утверждения WHERE один за другим, чтобы выяснить, какой из них фильтрует строки:

WHERE 1 = 1
AND c.Group = 'HR'
--AND c.bFlag IS NULL
--AND s.Report IN ('P', 'N')
--AND CONVERT(VARCHAR(6), c.changedate, 112) IN
--       (SELECT
--            CASE 
--                WHEN f.Quarter = 'Q1' THEN CONVERT(VARCHAR(4), YEAR(@f_yr) - 1) + f.FyMonthNumber
--                WHEN f.Quarter = 'ALL' AND f.FyMonth IN ('OCT', 'NOV', 'DEC') THEN CONVERT(VARCHAR(4), YEAR(@f_yr) - 1, 112) + f.FyM
--                ELSE CONVERT(VARCHAR(4), YEAR(@f_yr), 112) + f.FyM 
--            END AS FY_MONTH
--        FROM fis f
--        WHERE f.Quarter = @qrt)
--AND c.GroupLabel = 'Hr' + @dnum

Затем еще одно утверждение:

WHERE 1 = 1
AND c.Group = 'HR'
AND c.bFlag IS NULL
--AND s.Report IN ('P', 'N')
--AND CONVERT(VARCHAR(6), c.changedate, 112) IN
--       (SELECT
--            CASE 
--                WHEN f.Quarter = 'Q1' THEN CONVERT(VARCHAR(4), YEAR(@f_yr) - 1) + f.FyMonthNumber
--                WHEN f.Quarter = 'ALL' AND f.FyMonth IN ('OCT', 'NOV', 'DEC') THEN CONVERT(VARCHAR(4), YEAR(@f_yr) - 1, 112) + f.FyM
--                ELSE CONVERT(VARCHAR(4), YEAR(@f_yr), 112) + f.FyM 
--            END AS FY_MONTH
--        FROM fis f
--        WHERE f.Quarter = @qrt)
--AND c.GroupLabel = 'Hr' + @dnum

И так до тех пор, пока вы не попадете в точку, когда строки не возвращаются

Эта техника в конечном итоге приведет вас к части (частям) запроса, которая фильтрует строки

Если исходный набор данных возвращает слишком большое количество строк, может быть дорого извлечь их все во время отладки, поэтому я бы рекомендовал закомментировать их и использовать вместо этого COUNT (*):

SELECT COUNT(*)
/*
c.GroupLabel AS ORG_Code,
   CONVERT (VARCHAR(7), FORMAT((CONVERT(DATE, c.changedate)), 'MM-yyyy')) AS [MONTH],
   COUNT(DISTINCT CASE s.TestType 
         WHEN 'IR' THEN c.changedate
              ELSE NULL END) AS TEST_DAYS,
   COUNT(DISTINCT c.changedate) AS ALLDAYS,
   COUNT(s.Id) AS total,
   (CASE WHEN (@u_cnt IS NULL) THEN -1 
         ELSE @u_cnt
         END) AS board_cnt,
   FORMAT((COUNT(s.Id) / CASE
                                WHEN (@u_cnt IS NULL) THEN -1 
                                ELSE @u_cnt
                                END), 'P0') AS pct_tested_text,

   CASE WHEN 100 * (COUNT(s.Id) / CASE 
                                   WHEN (@u_cnt IS NULL) THEN -1 
                                   ELSE @u_cnt 
                                   END) >= 15 
               AND (COUNT(DISTINCT CASE s.TestType
                          WHEN 'IR' THEN c.changedate
                          ELSE NULL END)) >= 4  
   THEN 'Yes'
   ELSE 'NO' END 
*/
FROM cforms c 
0 голосов
/ 22 января 2019

Ваш главный вопрос: почему вы не получаете данные для данного запроса? Итак, вы хотите отладить и проверить, где проблема.

Таким образом, для данного параметра,

DECLARE @u_cnt INT;
DECLARE @f_yr DATE;
DECLARE @qrt VARCHAR(3);
DECLARE @dnum VARCHAR(5);


SET @u_cnt = 10000;
SET @f_yr = '2002-05-20';
SET @qrt = 'Q2';
SET @dnum = '43234';

так что начните с базового

 select * 
    FROM cforms c 
    --INNER JOIN spitems sp
    --ON c.Id = s.FormId
    WHERE c.Group = 'HR'
    --AND c.bFlag IS NULL
--AND s.Report IN ('P', 'N')

обратите внимание на часть комментариев, возвращает ли она данные, если да, тогда раскомментируйте AND c.bFlag IS NULL и таким образом раскомментируйте другую часть.

Вы уверены, что это будет INNER JOIN или LEFt JOIN?

Поместите подзапрос периода в временную таблицу, хотя это не главная причина, если он возвращает меньше записей, вы также можете использовать CTE,

Create table #tempperiod(period varchar(6))
insert into #tempperiod(period)
select 
            cast(year(@f_yr) + 
                case
                    when f.Quarter = 'Q1'
                        then (-1)
                    when f.Quarter = 'ALL'
                        and f.FyMonthNumber in ('10', '11', '12')
                        then (-1)
                    else (0)
                end as varchar(4))
                + f.FyMonthNumber 
        from FyQm f
        where f.Quarter = @qrt

-- in order to test,does it return any records,does it return desire output
select * from #tempperiod
  1. Проверка пробела (LTRIM and RTRIM) в столбцах, который используется в предикате.
  2. Избегайте деления на 0 в вашем случае
  3. Если это действительно, INNER JOIN, тогда используйте EXISTS предложение, потому что вам не нужны spitems sp столбцы.
  4. Что такое ORDER BY 1? GroupLabel? тогда они вам не нужны в предложении Order, потому что все строки будут 'HR' + '43234'
  5. ВСЕ, вам не нужно Order by, coz Group By отсортирует его для вас, и это единственное требование.
  6. Тщательно проверьте данные #tempperiod, формат такой же как

    CONVERT (VARCHAR (6), c.changeate, 112)

0 голосов
/ 19 января 2019

Я переформатировал ваш код с замечаниями:

declare @u_cnt int, @f_yr date, @qrt varchar(3), @dnum varchar(5);
select @u_cnt = 10000, @f_yr = '20020520', @qrt = 'Q2', @dnum = '43234';

select c.GroupLabel as ORG_CODE
      -- Assuming c.changedate is datetime, otherwise cast(c.changedate as datetime)
    , format(c.changedate, 'MM-yyyy') as [MONTH] 
    , count(distinct case s.TestType when 'IR' then c.changedate else null end) as IR_TEST_DAYS
    , count(distinct c.changedate) as TEST_DAYS
    , count(s.Id) as TOTAL
    , (case when (@u_cnt is null) then - 1 else @u_cnt end) as BOARD_CNT
    , format((count(s.Id) /
        -- avoiding also division by 0
        case when isnull(@u_cnt, 0) = 0
            then - 1
            else @u_cnt end), 'P0')
        as PCT
    , case
        when 100 * (count(s.Id) / 
            -- avoiding also division by 0
            case when isnull(@u_cnt, 0) = 0
                then - 1
                else @u_cnt
            end) >= 15
            and (count(distinct case s.TestType
                    when 'IR' then c.changedate else null
                end)) >= 4
        then 'Yes' else 'NO'
    end as PCT_TEST_COMP
from cforms c
join spitems s on (c.Id = s.FormId)
where c.group = 'HR'
    and c.bFlag is null
    and s.Report in ('P', 'N')
    and convert(varchar(6), c.changedate, 112) in -- yyyymm (ISO format)
        (
        select 
            cast(year(@f_yr) + 
                case
                    when f.Quarter = 'Q1'
                        then (-1)
                    when f.Quarter = 'ALL'
                        and f.FyMonthNumber in ('10', '11', '12')
                        then (-1)
                    else (0)
                end as varchar(4))
                + f.FyMonthNumber -- JAN = '01' or '1' ?
        from FyQm f
        where f.Quarter = @qrt
        )
    and c.GroupLabel = 'Hr' + @dnum
group by c.GroupLabel
      -- Assuming c.changedate is datetime, otherwise cast(c.changedate as datetime)
    , format(c.changedate, 'MM-yyyy')
order by ORG_CODE, [MONTH];

Не могли бы вы проверить, если FyQm.FyMonthNumber равно varchar(2) или char(2) и представляет январь как '01' вместо '1' ?

0 голосов
/ 19 января 2019

Моя ставка на разные определения столбцов

DECLARE @qrt VARCHAR(3);

vs

whatever is FROM FyQm f   WHERE f.Quarter = @qrt

'Q2 ' with a blank or null probably does not equal  f.Quarter which may be defined as VARCHAR(2)

Возможно, мы могли бы попробовать этот sql, чтобы увидеть, что у каждого критерия есть несколько строк

Select
  Sum(1) as cntAll
 ,Sum (CASE When c.Group = 'HR' Then 1 Else 0 End) as cntGroup  
 ,Sum (CASE When c.bFlag IS NULL Then 1 Else 0 End) as cntbFlag
 ,Sum (CASE When s.Report IN ('P', 'N') Then 1 Else 0 End) as cntsReport
 ,Sum (CASE When CONVERT(VARCHAR(6), c.changedate, 112) 
    IN ('200204', '200205', '200206') Then 1 Else 0 End) as cntchangedate
 ,Sum (CASE When c.GroupLabel = 'Hr43234' Then 1 Else 0 End) as cntGroupLabel

FROM cforms c 
INNER JOIN spitems s
ON c.Id = s.FormId

Может быть, пора последовать совету @scsimon и добавить обратно критерии по одному и посмотреть, какой из них блокирует все строки

--  WHERE c.Group = 'HR'
--  AND c.bFlag IS NULL
--  AND s.Report IN ('P', 'N')
--  AND CONVERT(VARCHAR(6), c.changedate, 112) IN ('200204', '200205', '200206')
--  AND c.GroupLabel = 'Hr43234'
0 голосов
/ 18 января 2019

Попробуйте изменить это (посмотрите на 1-е преобразование):

...
AND CONVERT(VARCHAR(7), c.changedate, 120) IN
       (SELECT
            CASE 
                WHEN f.Quarter = 'Q1' THEN CONVERT(VARCHAR(4), YEAR(@f_yr) - 1) + '-' + f.FyMonthNumber
                WHEN f.Quarter = 'ALL' AND f.FyMonth IN ('OCT', 'NOV', 'DEC') THEN CONVERT(VARCHAR(4), YEAR(@f_yr) - 1, 112) + '-' + f.FyMonthNumber
                ELSE CONVERT(VARCHAR(4), YEAR(@f_yr), 112) + '-' + f.FyMonthNumber 
            END AS FY_MONTH
        FROM FyQm f
        WHERE f.Quarter = @qrt)
...

Вы конвертировали 112 (yyyymm) вместо 120 (yyyy-mm), и ваш внутренний выбор возвращает yyyy-mm

0 голосов
/ 17 января 2019

Все, что может ограничивать ваши данные, находится в этой части кода ниже. Я разбил его на части и добавил комментарии к , почему и , где они ограничены. Я думаю, что ваш CONVERT является виновником.

--this inner join will limit the rows to only those with matching Id and FormId
INNER JOIN spitems sp
ON c.Id = s.FormId

--of the rows already filtered via the JOIN, they are further limited to thous with the Group = 'HR', a NULL bFlag, and Report = to P or N
WHERE c.Group = 'HR'
AND c.bFlag IS NULL
AND s.Report IN ('P', 'N')


--The first convert here changed changedate to yyyymmd (notice the day). 
--In the sub-query, you seem to only be returning yyyymm formatted with a -, 
--thus this would return ZERO rows. varchar(6) could resolve this, 
--by dropping the day, but you'd need to add the hyphen or remove it from the `IN` clause
AND CONVERT(VARCHAR(7), c.changedate, 112) IN
       (SELECT
            CASE 
                WHEN f.Quarter = 'Q1' THEN CONVERT(VARCHAR(4), YEAR(@f_yr) - 1) + '-' + f.FyMonthNumber
                WHEN f.Quarter = 'ALL' AND f.FyMonth IN ('OCT', 'NOV', 'DEC') THEN CONVERT(VARCHAR(4), YEAR(@f_yr) - 1, 112) + '-' + f.FyMonthNumber
                ELSE CONVERT(VARCHAR(4), YEAR(@f_yr), 112) + '-' + f.FyMonthNumber 
            END AS FY_MONTH
        FROM FyQm f
        WHERE f.Quarter = @qrt)

--Lastly, there may be a case sensitivity here Hr vs HR or there just simply aren't any rows that match this predicate
AND c.GroupLabel = 'Hr' + @dnum

EDIT

Разрабатывая мой ответ выше ... Вы изменили часть своего предложения where. В частности, часть, где вы оцениваете c.changedate в список значений. Вы внесли изменения в:

AND CONVERT(VARCHAR(6), c.changedate, 112) IN ...

Это частичное исправление. Это приведет к удалению конечного значения DAY, которое у вас было раньше, и у вас останется YYYYMM. Однако в вашем подзапросе вы форматируете список значений как YYYYMM-? где? что бы то ни было f.FyMonthNumber. Как вы можете видеть, это никогда не будет соответствовать вашему исходному выражению convert, поскольку оно не имеет дефис . Первое, что нужно изменить, это удалить дефис из конкатенации строк. В вашем отредактированном сообщении вы уже сделали это, так что хорошая работа . Далее, проблема может заключаться в том, что ваш + не рассматривается как сложение вместо объединения, когда вы пытаетесь объединить его с f.FyMonthNumber. Если f.FyMonthNumber является int, то он добавит его.

DECLARE @f_yr DATE;
SET @f_yr = '2002-05-20';

SELECT CONVERT(VARCHAR(4), YEAR(@f_yr) - 1) + 02

Здесь вы хотите, чтобы он возвращал 200102, но он возвращает 2003, так как он выполняет сложение. Вы можете разыграть его как varchar или char, чтобы исправить это.

SELECT CONVERT(VARCHAR(4), YEAR(@f_yr) - 1) + cast('02' as varchar)

Наконец, проблема, с которой вы можете столкнуться, заключается в том, что если f.FyMonthNumber хранится как int, у него не будет начального нуля. Таким образом, для января он будет представлен как 1 вместо 01, и это также будет возвращать ноль строк за любой месяц до октября. Вы можете справиться с этим с помощью функции right.

DECLARE @f_yr DATE;
SET @f_yr = '2002-05-20';

SELECT CONVERT(VARCHAR(4), YEAR(@f_yr) - 1) + right('0' + cast('1' as varchar(2)),2) --a month as a single digit
SELECT CONVERT(VARCHAR(4), YEAR(@f_yr) - 1) + right('0' + cast('12' as varchar(2)),2) --a month with double digits

Сложив все это вместе, я подозреваю, что эта правка исправит вашу проблему. Однако я хотел бы отметить, что вы не оцениваете каких-либо выражений для Q2, Q3 или Q4 , если это применимо ...

DECLARE @u_cnt INT;
DECLARE @f_yr DATE;
DECLARE @qrt VARCHAR(3);
DECLARE @dnum VARCHAR(5);


SET @u_cnt = 10000;
SET @f_yr = '2002-05-20';
SET @qrt = 'Q2';
SET @dnum = '43234';




SELECT c.GroupLabel AS ORG_Code,
   CONVERT (VARCHAR(7), FORMAT((CONVERT(DATE, c.changedate)), 'MM-yyyy')) AS [MONTH],
   COUNT(DISTINCT CASE s.TestType 
         WHEN 'IR' THEN c.changedate
              ELSE NULL END) AS TEST_DAYS,
   COUNT(DISTINCT c.changedate) AS ALLDAYS,
   COUNT(s.Id) AS total,
   (CASE WHEN (@u_cnt IS NULL) THEN -1 
         ELSE @u_cnt
         END) AS board_cnt,
   FORMAT((COUNT(s.Id) / CASE
                                WHEN (@u_cnt IS NULL) THEN -1 
                                ELSE @u_cnt
                                END), 'P0') AS pct_tested_text,

   CASE WHEN 100 * (COUNT(s.Id) / CASE 
                                   WHEN (@u_cnt IS NULL) THEN -1 
                                   ELSE @u_cnt 
                                   END) >= 15 
               AND (COUNT(DISTINCT CASE s.TestType
                          WHEN 'IR' THEN c.changedate
                          ELSE NULL END)) >= 4  
   THEN 'Yes'
   ELSE 'NO' END 
FROM cforms c 
INNER JOIN spitems sp
ON c.Id = s.FormId
WHERE c.Group = 'HR'
AND c.bFlag IS NULL
AND s.Report IN ('P', 'N')
AND CONVERT(VARCHAR(6), c.changedate, 112) IN
       (SELECT
            CASE 
                WHEN f.Quarter = 'Q1' THEN CONVERT(VARCHAR(4), YEAR(@f_yr) - 1) + right('0' + cast(f.FyMonthNumber as varchar(2)))
                WHEN f.Quarter = 'ALL' AND f.FyMonth IN ('OCT', 'NOV', 'DEC') THEN CONVERT(VARCHAR(4), YEAR(@f_yr) - 1, 112) + right('0' + cast(f.FyMonthNumber as varchar(2)))
                ELSE CONVERT(VARCHAR(4), YEAR(@f_yr), 112) + right('0' + cast(f.FyMonthNumber as varchar(2)))
            END AS FY_MONTH
        FROM fis f
        WHERE f.Quarter = @qrt)
AND c.GroupLabel = 'Hr' + @dnum
GROUP BY c.GroupLabel, FORMAT((CONVERT(DATE, c.changedate)), 'MM-yyyy')
ORDER BY 1, FORMAT((CONVERT(DATE, c.changedate)), 'MM-yyyy');
...