我可以在SQL查询中使用什么来帮助我确定为什么查询不返回任何数据结果

时间:2019-01-16 16:35:15

标签: sql-server sql-server-2016 ssms-2016

有人可以协助我对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 :(得分:2)

所有可能限制您数据的内容都在下面的代码这一部分中。我将其分解,并在限制的为什么 where 中添加了注释。我认为您的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

编辑

详细说明我的答案...您更改了where子句的一部分。特别是您要评估c.changedate到值列表的部分。您已更改为:

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

这是部分修复。它将删除您之前的尾随DAY值,而剩下YYYYMM。但是,在子查询中,您将值列表的格式设置为YYYYMM-?,其中? f.FyMonthNumber是什么。如您所见,由于它没有连字符,因此它永远不会与原始convert语句匹配。首先要更改的是从字符串连接中删除连字符。在编辑过的帖子中,您已经做到了这一点,干得好。接下来,问题可能是当您尝试将+f.FyMonthNumber结合使用时,您的f.FyMonthNumber未被视为加法而不是串联。如果intDECLARE @f_yr DATE; SET @f_yr = '2002-05-20'; SELECT CONVERT(VARCHAR(4), YEAR(@f_yr) - 1) + 02 ,它将添加它。

varchar

在这里,您希望它返回200102,但是由于它正在执行加法,因此它返回2003。您可以将其转换为charSELECT CONVERT(VARCHAR(4), YEAR(@f_yr) - 1) + cast('02' as varchar) 来解决。

f.FyMonthNumber

最后,您可能遇到的一个问题是,如果int存储为1,则不会有前导零。因此,对于1月份,它将表示为01而不是right,并且对于10月份之前的任何月份,这也将返回零行。您可以使用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 函数来处理此问题。

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');

综合考虑,我怀疑此修改可以解决您的问题。不过,我要指出的是,如果适用的话,您不会评估 Q2,Q3或Q4的任何大小写表达式 ...

{{1}}

答案 1 :(得分:1)

尝试更改为该值(查看第一个转换):

ProcessorContext::forward

您正在转换112(public KeyValue<String, Message> transform(String key, Message message) { Iterable<Message> messages = generateMultipleFromOne(message); messages.forEach(m->context.forward(key, m)); return null; } )而不是120(... 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) ... ),并且内部选择返回yyyymm

答案 2 :(得分:1)

JOIN或/和WHERE子句可能是一个原因。 下面的基本推导方法是找出查询的哪一部分给出了这样的结果:

首先,消除所有WHERE子句,并通过以下方式设置WHERE来检查当前的JOIN是否可以返回行:

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

然后,另一句话:

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 

答案 3 :(得分:0)

我的赌注是在不同的列定义上

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'

答案 4 :(得分:0)

我用备注重新格式化了您的代码:

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 '

答案 5 :(得分:0)

您的主要问题是为什么您没有获取给定查询的数据? 因此,您想调试并检查问题出在哪里。

对于给定的参数,

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吗?

将period子查询放入临时表中,虽然这不是主要原因,但如果返回的记录较少,则也可以使用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 1GroupLabel?那么您在Order子句中就不需要它们了,因为所有行都是'HR'+'43234'
  5. 最重要的是,您根本不需要Order by,因为Group By会为您排序,这是唯一的要求。
  6. 彻底检查#tempperiod数据,其格式与

    相同

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