Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jsp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 为什么我对联接表的计数不正确?_Sql_Tsql_Count_Left Join_Sql Server 2014 - Fatal编程技术网

Sql 为什么我对联接表的计数不正确?

Sql 为什么我对联接表的计数不正确?,sql,tsql,count,left-join,sql-server-2014,Sql,Tsql,Count,Left Join,Sql Server 2014,我有以下表格: STUDYA别名J 试验别名G SPRINT别名H 还有另一个名为LOGIN的表,我正在匹配LOGINID 我在SQL Server 2014上运行了以下查询: SELECT 'COUNTS', COUNT(G.LOGINID), COUNT(H.LOGINID), COUNT(J.LOGINID) FROM LOGIN F LEFT OUTER JOIN TRIALS G ON F.LOGINID= G.LOGINID AND G.RCD_NUM = F.RCD_N

我有以下表格:

STUDYA别名J

试验别名G

SPRINT别名H

还有另一个名为LOGIN的表,我正在匹配LOGINID

我在SQL Server 2014上运行了以下查询:

SELECT 'COUNTS', COUNT(G.LOGINID), COUNT(H.LOGINID), COUNT(J.LOGINID)
 FROM LOGIN F 
LEFT OUTER JOIN  TRIALS G ON  F.LOGINID= G.LOGINID AND G.RCD_NUM = 
 F.RCD_NUM 
LEFT OUTER JOIN  SPRINT H ON  F.LOGINID= H.LOGINID AND H.RCD_NUM = 
 F.RCD_NUM
LEFT OUTER JOIN  STUDYA J ON  F.LOGINID= J.LOGINID AND J.RCD_NUM = 
 F.RCD_NUM  

WHERE ( ( F.EFFDT = 
(SELECT MAX(F_ED.EFFDT) FROM PS_JOB F_ED 
WHERE F.LOGINID = F_ED.LOGINID 
  AND F.RCD_NUM = F_ED.RCD_NUM 
  AND F_ED.EFFDT <= SUBSTRING(CONVERT(CHAR,GETDATE(),121), 1, 10)) 
AND F.EFFSEQ = 
(SELECT MAX(F_ES.EFFSEQ) FROM PS_JOB F_ES 
 WHERE F.LOGINID = F_ES.LOGINID 
  AND F.RCD_NUM = F_ES.RCD_NUM 
  AND F.EFFDT = F_ES.EFFDT) )
您可以看到最后一列COUNTJ.LOGINID显示了5条记录,而在上面查询的实际表中实际上只有4条记录。我认为这是因为LOGINID 2867在试验表中有2行,在STUDYA中有1行


我对此进行了研究,建议在加入之前进行聚合。不过,我正在努力寻找最好的方法。感谢您的帮助

您需要获得不同的计数

 SELECT 'COUNTS', COUNT(distinct G.LOGINID), COUNT(distinct 
 H.LOGINID), COUNT(distinct J.LOGINID) ..

根据您的数据和用例,您可能会从您提到的方法中获得性能优势:聚合然后加入

SELECT
 'COUNTS',
 COUNT(G.LOGINID) distinct_g, SUM(G.ROW_COUNT) row_count_g,
 COUNT(H.LOGINID) distinct_h, SUM(H.ROW_COUNT) row_count_h,
 COUNT(J.LOGINID) distinct_j, SUM(J.ROW_COUNT) row_count_j
FROM
 LOGIN F 
LEFT OUTER JOIN
(
 SELECT LOGINID, RCD_NUM, COUNT(*) AS ROW_COUNT FROM TRIALS GROUP BY LOGINID, RCD_NUM
)
 G
  ON  F.LOGINID = G.LOGINID
  AND F.RCD_NUM = G.RCD_NUM 
LEFT OUTER JOIN
(
 SELECT LOGINID, RCD_NUM, COUNT(*) AS ROW_COUNT FROM SPRINT GROUP BY LOGINID, RCD_NUM
)
 H
  ON  F.LOGINID = H.LOGINID
  AND F.RCD_NUM = H.RCD_NUM 
LEFT OUTER JOIN
(
 SELECT LOGINID, RCD_NUM, COUNT(*) AS ROW_COUNT FROM STUDYA GROUP BY LOGINID, RCD_NUM
)
 J
  ON  F.LOGINID = J.LOGINID
  AND F.RCD_NUM = J.RCD_NUM 

WHERE ( ( F.EFFDT = 
(SELECT MAX(F_ED.EFFDT) FROM PS_JOB F_ED 
WHERE F.LOGINID = F_ED.LOGINID 
  AND F.RCD_NUM = F_ED.RCD_NUM 
  AND F_ED.EFFDT <= SUBSTRING(CONVERT(CHAR,GETDATE(),121), 1, 10)) 
AND F.EFFSEQ = 
(SELECT MAX(F_ES.EFFSEQ) FROM PS_JOB F_ES 
 WHERE F.LOGINID = F_ES.LOGINID 
  AND F.RCD_NUM = F_ES.RCD_NUM 
  AND F.EFFDT = F_ES.EFFDT) )
优化程序可以使用谓词下推/类似宏的扩展来确保只对相关行进行聚合,并保留索引的使用

此模式还允许您获取其他统计信息,例如每个登录/rcd组合的最小/最大日期

编辑:

另一种模式可能包括

SELECT
 'COUNTS',
 SUM(G.ROW_COUNT) row_count_g,
 SUM(H.ROW_COUNT) row_count_h,
 SUM(J.ROW_COUNT) row_count_j
FROM
 LOGIN F 
OUTER APPLY
(
 SELECT COUNT(*) AS ROW_COUNT FROM TRIALS WHERE LOGINID = F.LOGINID AND RCD_NUM = F.RCD_NUM
)
  G
OUTER APPLY
(
 SELECT COUNT(*) AS ROW_COUNT FROM SPRINT WHERE LOGINID = F.LOGINID AND RCD_NUM = F.RCD_NUM
)
  H
OUTER APPLY
(
 SELECT COUNT(*) AS ROW_COUNT FROM STUDYA WHERE LOGINID = F.LOGINID AND RCD_NUM = F.RCD_NUM
)
  J

WHERE ( ( F.EFFDT = 
(SELECT MAX(F_ED.EFFDT) FROM PS_JOB F_ED 
WHERE F.LOGINID = F_ED.LOGINID 
  AND F.RCD_NUM = F_ED.RCD_NUM 
  AND F_ED.EFFDT <= SUBSTRING(CONVERT(CHAR,GETDATE(),121), 1, 10)) 
AND F.EFFSEQ = 
(SELECT MAX(F_ES.EFFSEQ) FROM PS_JOB F_ES 
 WHERE F.LOGINID = F_ES.LOGINID 
  AND F.RCD_NUM = F_ES.RCD_NUM 
  AND F.EFFDT = F_ES.EFFDT) )

我强烈建议您不要使用g、h、j作为表别名。您正在混淆代码。表名不长,TRIALS.LOGINID仅比G.LOGINID长5个字符,但非常容易调试、维护等。示例数据也与示例输出不匹配。您在试用中有7行,但您的示例输出显示9?我厌倦了您的解决方案,但是我收到了一条错误消息:每个GROUP BY表达式必须至少包含一个非外部引用的列。有什么想法吗?谢谢这似乎很有效!因此,如果我错了,请纠正我,这是在连接到其他表之前,对每个表中的行总数求和?行计数是sql函数吗?非常感谢。因为ROW\u COUNT只给该列命名为ROW\u COUNT。您可以使用乐高,然后使用SUMG.lego。子查询确保每个LOGINID,RCD_NUM只返回一行,这样在连接结果时不会发生重复。子查询返回的字段之一是使用COUNT*将输出行的多少个源行聚合到一起。然后你可以把这些值加起来。
(No column name)   (No column name)   (No column name)   (No column name) 
  COUNTS                  9                  5                  5
 SELECT 'COUNTS', COUNT(distinct G.LOGINID), COUNT(distinct 
 H.LOGINID), COUNT(distinct J.LOGINID) ..
SELECT
 'COUNTS',
 COUNT(G.LOGINID) distinct_g, SUM(G.ROW_COUNT) row_count_g,
 COUNT(H.LOGINID) distinct_h, SUM(H.ROW_COUNT) row_count_h,
 COUNT(J.LOGINID) distinct_j, SUM(J.ROW_COUNT) row_count_j
FROM
 LOGIN F 
LEFT OUTER JOIN
(
 SELECT LOGINID, RCD_NUM, COUNT(*) AS ROW_COUNT FROM TRIALS GROUP BY LOGINID, RCD_NUM
)
 G
  ON  F.LOGINID = G.LOGINID
  AND F.RCD_NUM = G.RCD_NUM 
LEFT OUTER JOIN
(
 SELECT LOGINID, RCD_NUM, COUNT(*) AS ROW_COUNT FROM SPRINT GROUP BY LOGINID, RCD_NUM
)
 H
  ON  F.LOGINID = H.LOGINID
  AND F.RCD_NUM = H.RCD_NUM 
LEFT OUTER JOIN
(
 SELECT LOGINID, RCD_NUM, COUNT(*) AS ROW_COUNT FROM STUDYA GROUP BY LOGINID, RCD_NUM
)
 J
  ON  F.LOGINID = J.LOGINID
  AND F.RCD_NUM = J.RCD_NUM 

WHERE ( ( F.EFFDT = 
(SELECT MAX(F_ED.EFFDT) FROM PS_JOB F_ED 
WHERE F.LOGINID = F_ED.LOGINID 
  AND F.RCD_NUM = F_ED.RCD_NUM 
  AND F_ED.EFFDT <= SUBSTRING(CONVERT(CHAR,GETDATE(),121), 1, 10)) 
AND F.EFFSEQ = 
(SELECT MAX(F_ES.EFFSEQ) FROM PS_JOB F_ES 
 WHERE F.LOGINID = F_ES.LOGINID 
  AND F.RCD_NUM = F_ES.RCD_NUM 
  AND F.EFFDT = F_ES.EFFDT) )
SELECT
 'COUNTS',
 SUM(G.ROW_COUNT) row_count_g,
 SUM(H.ROW_COUNT) row_count_h,
 SUM(J.ROW_COUNT) row_count_j
FROM
 LOGIN F 
OUTER APPLY
(
 SELECT COUNT(*) AS ROW_COUNT FROM TRIALS WHERE LOGINID = F.LOGINID AND RCD_NUM = F.RCD_NUM
)
  G
OUTER APPLY
(
 SELECT COUNT(*) AS ROW_COUNT FROM SPRINT WHERE LOGINID = F.LOGINID AND RCD_NUM = F.RCD_NUM
)
  H
OUTER APPLY
(
 SELECT COUNT(*) AS ROW_COUNT FROM STUDYA WHERE LOGINID = F.LOGINID AND RCD_NUM = F.RCD_NUM
)
  J

WHERE ( ( F.EFFDT = 
(SELECT MAX(F_ED.EFFDT) FROM PS_JOB F_ED 
WHERE F.LOGINID = F_ED.LOGINID 
  AND F.RCD_NUM = F_ED.RCD_NUM 
  AND F_ED.EFFDT <= SUBSTRING(CONVERT(CHAR,GETDATE(),121), 1, 10)) 
AND F.EFFSEQ = 
(SELECT MAX(F_ES.EFFSEQ) FROM PS_JOB F_ES 
 WHERE F.LOGINID = F_ES.LOGINID 
  AND F.RCD_NUM = F_ES.RCD_NUM 
  AND F.EFFDT = F_ES.EFFDT) )