【问题标题】:SQL divide and group by idSQL 按 id 划分和分组
【发布时间】:2012-09-06 20:20:54
【问题描述】:

我有以下查询。我正在尝试提取具有特定标准的记录数,然后除以按 cstmr_id 分组的记录总数。但是我遇到了一个错误。任何帮助,将不胜感激。此外,此语句是一个子查询,是更大的选择查询的一部分。我正在使用 SQL Server 2005

出现“'/' 附近的语法错误”错误

声明:

((SELECT count(*) FROM cstmr WHERE active=1 AND cstmr_type LIKE '%dtr%' 
GROUP BY cstmr_id) 
/  --division sign here. dividing top query by bottom
(SELECT count(*) FROM cstmr WHERE cstmr_type LIKE '%dtr%'
GROUP BY cstmr_id) ) As cstmr_rate

cstmr 表中的样本数据:

cstmr_id    cstmr_type    active
3423        dtr           1
1236        dtr           1
1842        dtr           1
8273        sys           2
9384        aod           1
3847        sys           2

样本预期结果:

cstmr_id    cstmr_rate
3423        88.98
1236        25.21
1842        58.01

基本伪代码

仅选择“dtr”类型的活跃客户,然后除以客户总数。然后显示每个客户的这个派生比率。这是一个非常基本的等式,使用同一个表“cstr”

【问题讨论】:

  • 实际错误和完整的 sql 语句很可能会有所帮助
  • 好吧,我收到“'/' 附近的语法错误”
  • 还有你为什么在里面有group by?如果cstmr_id 是唯一的,则COUNT(*) 将始终为1。
  • 你为什么不喜欢元音? cstmr 的输入速度真的比 customer 这样的单词快吗?
  • @dido 请发布一些示例数据。预期的结果很好,但结果之前的样本数据会好得多

标签: sql sql-server database sql-server-2008


【解决方案1】:
;WITH x AS 
(
  SELECT cstmr_id, active, c = COUNT(*) 
   FROM dbo.cstmr WHERE cstmr_type LIKE '%dtr%'
   GROUP BY cstmr_id, active
), 
cr(cstmr_id, cstmr_rate) AS
(
  SELECT cstmr_id, 
   SUM(CASE active WHEN 1 THEN c ELSE 0 END)*1.0 / SUM(c) 
  FROM x GROUP BY cstmr_id
)
SELECT cr.cstmr_id, cr.cstmr_rate --, other columns
FROM cr
--INNER JOIN -- other tables from your larger query

【讨论】:

    【解决方案2】:

    您似乎缺少外部SELECT

    select -- You are missing this
    (
        (SELECT cast(count(*) as decimal(10,2))
        FROM cstmr 
        WHERE active=1 AND cstmr_type LIKE '%dtr%' 
        GROUP BY cstmr_id) 
    /  --division sign here. dividing top query by bottom
        (SELECT cast(count(*) as decimal(10,2))
        FROM cstmr 
        WHERE cstmr_type LIKE '%dtr%'
        GROUP BY cstmr_id) 
    ) As cstmr_rate
    

    【讨论】:

    • 我没有投反对票,但问题清楚地表明这是一个子查询。我想这就是投反对票的原因。
    • @GordonLinoff 很好,没有看到整个查询很困难,但我只是在 sql-server 2005 上运行了一个类似的查询,它没有任何问题
    • @dido 请查看我的编辑,在count() 周围尝试cast(),因为它返回int
    • 好吧,我试过了,但它返回错误:子查询返回超过 1 个值。当子查询跟随 =、!=、 时,这是不允许的
    • @dido 那是因为你有一个 GROUP BY 出于某种原因,正如我在上面的评论中提到的那样。删除两个GROUP BY 行,然后重试。
    【解决方案3】:

    这可能不起作用,因为这两个查询返回的记录不止一条。 SQL Server 无法将结果集除以结果集。

    尝试使用连接来提取这些计数。

    编辑

    类似这样的:

    SELECT 
        c.cstmr_id,
        c1/c2 AS 'cstmr_rate'
    FROM cstmr as c
    JOIN (
        SELECT cstmr_id, count(*) AS 'c1'
        FROM cstmr 
        WHERE active=1 
        AND cstmr_type LIKE '%dtr%' 
        GROUP BY cstmr_id
        ) AS sub1 ON c.cstmr_id = sub1.cstmr_id
    JOIN (
        SELECT cstmr_id, count(*) AS 'c2'
        FROM cstmr 
        WHERE cstmr_type LIKE '%dtr%'
        GROUP BY cstmr_id
        ) AS sub2 ON c.cstmr_id = sub2.cstmr_id
    

    EDIT2

    假设 active 为 1 或 0,这也可能有效:

    SELECT
        cstmr_id,
        SUM(Active)/COUNT(*)  AS 'cstmr_rate'
    FROM cstmr
    GROUP BY cstmr_id
    

    【讨论】:

    • 您好,我尝试了您的第一个解决方案,但在第一个 GROUP BY 上收到一条错误消息“列名 'cstmr_id' 无效”
    • 如果有点,你的第二个查询返回错误,可能需要转换。它还在做整数数学。
    【解决方案4】:

    除了你的语法问题,还有更简单的方法来表达你想要的:

    select count(distinct case when active = 1 then cstmr_id end)*1.0 / count(distinct cstmr_id)
    from cstmr
    where cstmr_type like '%dtr%'
    

    如果cstmr_id在cstmr表中没有重复,可以进一步简化为:

    select sum(case when active = 1 then 1.0 else 0.0 end) / count(*)
    from cstmr
    where cstmr_type like '%dtr%'
    

    甚至:

    select avg(active*1.0)
    from cstmr
    where cstmr_type like '%dtr%'
    

    请注意,我还将整数转换为浮点数。如您所写,它产生的值不是 0 就是 1,因为 SQL Server 对整数进行整数运算。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-17
      • 1970-01-01
      • 2016-03-10
      • 2012-02-04
      • 1970-01-01
      • 2014-01-31
      • 1970-01-01
      相关资源
      最近更新 更多