有人可以协助我对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');
答案 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
未被视为加法而不是串联。如果int
是DECLARE @f_yr DATE;
SET @f_yr = '2002-05-20';
SELECT CONVERT(VARCHAR(4), YEAR(@f_yr) - 1) + 02
,它将添加它。
varchar
在这里,您希望它返回200102,但是由于它正在执行加法,因此它返回2003。您可以将其转换为char
或SELECT 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
LTRIM and RTRIM
)。INNER JOIN
然后使用EXISTS
子句,因为您不需要spitems sp
列。ORDER BY 1
? GroupLabel
?那么您在Order子句中就不需要它们了,因为所有行都是'HR'+'43234'Order by
,因为Group By
会为您排序,这是唯一的要求。彻底检查#tempperiod数据,其格式与
相同CONVERT(VARCHAR(6),c.changedate,112)