MSSQL:SUM LEFT JOIN GROUP BY

时间:2017-11-30 08:02:55

标签: sql sql-server tsql

我有两张桌子:

CSF和CN

     CSF                       CN
--------------           ------------------------------------
| CSF-Number |           | Code | CSF | DateTime            |
--------------           -----------------------------------|
| aaa        |           | A    | aaa | 2017-07-03T08:00:00 |
| bbb        |           | B    | ddd | 2017-07-04T08:00:00 |
| ccc        |           | C    | ccc | 2017-07-05T08:00:00 |
| ddd        |           | C    | aaa | 2017-07-06T08:00:00 |
--------------           ------------------------------------

正如您所看到的,CSF-Number是表CN中的外键。

我试图获得的是获得2笔钱。我想知道有多少CSF-Number在表CN

中有一个条目

结果应如下所示:

     Result Table
-----------------------
| Description | COUNT |
-----------------------
| With CN     |  75%  |
| Without CN  |  25%  |
-----------------------

我不知道哪个CSF-Numbers有条目。我只想根据CSF中的条目将总和视为百分比。

我不是SQL的新手但不知何故我无法解决这个问题:-)

谢谢!

更新

请注意,表CN可以有多个CSF-Number条目。 (参见表CN,其中有2个CSF条目' aaa')

更新2 添加了按日期和时间过滤的DateTime列

6 个答案:

答案 0 :(得分:0)

试试这个

PHP_EOL

答案 1 :(得分:0)

试试这个

WITH CTE
AS
(
  SELECT
  TotalCount = CAST(COUNT(CSF.CSF_NUMBER) AS NUMERIC(19,2)),
  WithCode = CAST(SUM(CASE WHEN CN.CODE IS NOT NULL THEN 1 ELSE 0 END) AS NUMERIC(19,2)),
  WithOutCode = CAST(SUM(CASE WHEN CN.CODE IS NULL THEN 1 ELSE 0 END) AS NUMERIC(19,2))
  FROM CSF
  LEFT JOIN CN
  ON CSF.CSF_NUMBER = CN.CSF
)
SELECT
Description ='With CN',
COUNT  = (WithCode/TotalCount)*100
FROM CTE
UNION ALL
SELECT
Description ='Without CN',
COUNT  = (WithOutCode/TotalCount)*100
FROM CTE

答案 2 :(得分:0)

试试这个,

SELECT 'With CN' Description,CAST(CAST((SELECT COUNT(CSF) FROM CN)*1.0/(SELECT COUNT(CSF_NUM) FROM CSF)*100 AS NUMERIC(8,0)) AS VARCHAR)+'%' [COUNT]
UNION ALL
SELECT 'Without CN' Description,CAST(CAST((SELECT COUNT(CSF_NUM) FROM CSF WHERE CSF_NUM not in(SELECT CSF FROM CN))*1.0/(SELECT COUNT(CSF_NUM) FROM CSF)*100 AS NUMERIC(8,0)) AS VARCHAR)+'%'[COUNT]

<强>输出:

Description COUNT
With CN     75%
Without CN  25%

<强> UPDATE1

SELECT 'With CN' Description,CAST(CAST((SELECT COUNT(DISTINCT CSF) FROM CN)*1.0/(SELECT COUNT(DISTINCT CSF_NUM) FROM CSF)*100 AS NUMERIC(8,0)) AS VARCHAR)+'%' [COUNT]
UNION ALL
SELECT 'Without CN' Description,CAST(CAST((SELECT COUNT(DISTINCT CSF_NUM) FROM CSF WHERE CSF_NUM not in(SELECT CSF FROM CN))*1.0/(DISTINCT SELECT COUNT(CSF_NUM) FROM CSF)*100 AS NUMERIC(8,0)) AS VARCHAR)+'%'[COUNT]

答案 3 :(得分:0)

DECLARE @res decimal(18,2) 

SELECT @res = CAST(100*SUM(CASE WHEN Code IS NULL THEN 0 ELSE 1 END)/COUNT(*) as decimal(18,2))
FROM CSF s
LEFT JOIN CN n
    ON s.[CSF-Number] = n.CSF

SELECT  'With CN' as [Description],
        @res as [COUNT]
UNION ALL
SELECT 'Without CN',
        100-@res 

输出:

Description COUNT
With CN     75.00
Without CN  25.00

<强>更新

SELECT @res = CAST(100*SUM(CASE WHEN Code IS NULL THEN 0 ELSE 1 END)/COUNT(*) as decimal(18,2))
FROM CSF s
OUTER APPLY(
    SELECT TOP 1 *
    FROM CN 
    WHERE s.[CSF-Number] = CSF
) as n

在这种情况下,使用 - 外部申请。

一些解释:

Here是对OUTER / CROSS APPLY的一个很好的解释。

基本上,我们加入2个表。左连接(或外部应用,在这种情况下的差异是我们指定TOP 1所以我们只得到第一次出现或根本没有出现)将带来CSF表和所有对应行的所有行来自CN表。

如果CN表中没有行 - 将带来NULL。然后我们使用case语句来使NULL - 0而不是NULLS - 1,总结它们,这里我们得到了一些数据。乘以100,除以所有CSF的数量。我们得到了百分比。

答案 4 :(得分:0)

count函数仅对非空值递增,因此所有必须计数的是代码本身,并自动计算任何NULL。

WITH
      cte AS (
                  SELECT
                        COUNT(CSF.CSF_NUMBER) * 1.0 AS all_csfs
                      , COUNT(CN.CODE)              AS all_cns
                  FROM CSF
                  LEFT JOIN CN ON CSF.CSF_NUMBER = CN.CSF
            )
SELECT
      'With CN'                    AS [description]
    , (all_cns / all_csfs) * 100.0 AS [Count]
FROM cte
UNION ALL
SELECT
      'Without CN'
    ,  ((all_csfs - all_cns) / all_csfs) * 100.0 
FROM cte

答案 5 :(得分:0)

你可以使用它。

SceneGenerator

结果:

SELECT 
    (CASE WHEN N.CSF IS NULL THEN 'Without CN' ELSE 'With CN' END) Description, 
    (100 * COUNT(DISTINCT C.[CSF-Number]) ) / (SUM(COUNT(DISTINCT C.[CSF-Number])) OVER())  [COUNT]
FROM @CSF C 
    LEFT JOIN @CN N ON C.[CSF-Number] = N.CSF
GROUP BY 
    (CASE WHEN N.CSF IS NULL THEN 'Without CN' ELSE 'With CN' END)