如果列具有特定值,则在SQL中聚合/分组表行

时间:2011-04-22 13:53:58

标签: sql xslt sql-server-2005

我正在处理一个相当毛茸茸的Stored Proc,它返回XML(XML用样式表转换并打印到页面;本质上是XML格式的GridView)。我需要将多行(当然具有相同的ID)聚合成单行,前提是特定列的值不是两个特定值之一(在这种情况下,列是没有汇总)。

实际上我需要执行以下操作(伪代码):

select quoteID, customerName, shippingCharges, description, /*other columns*/
from quotes q
    inner join customers c on q.customerID = c.customerID
where shipDate between @fromDate and @toDate
for xml explicit

if description != "Insurance" and description != "Pickup":
    /*aggregate the rows for that quoteID into one single row
      adding together charges and the like as needed*/  
else:
    /*nothing - okay to have multiple rows*/

我应该如何处理这种类型的逻辑?我的第一个猜测是将所有值放入临时表(或CTE),然后以某种方式检查所有数据,以查看是否需要提取和组合行,但我正在绘制一个空白,以确定如何实际完成,这通常是一个指标,它正确的做法......

这会在XSL转换文件中做得更好(也许更容易吗?)吗?我的选择仅限于三个选项:

  1. 在存储过程中聚合,保持XSLT不变
  2. 在XSLT中聚合,保持存储过程不变
  3. 使用当前返回数据的方式无法实现(或者在没有大量耗时的解决方法的情况下无法实现)
  4. 修改

    我面临的一个问题是记录通常具有相同的ID字段,因此总计出错是因为我正在对整个记录求和(计算我想要的字段的总数我不想要的字段。

    例如,记录可能类似于:

    1234    Insurance           54.65
    1234    Shipping Charge     160.00
    1234    Some Other Charge   15.00
    

    我希望完成的结果是这样的:

    1234    Shipment    175.00
    1234    Insurance   54.65
    

    发生了什么事:

    1234    Shipment    229.65
    1234    Insurance   229.65
    

    它正在抛弃总数。

    我使用的策略是创建一个名为“AggregateData”的CTE,它按ID和描述汇总各种金额和组;这是失败的,因为它给出了上述结果(每个描述的总和,因此值出现两次并在报告上添加两次)。我得到的最接近的是不按描述对其进行分组,而是将其包装在Max函数中(是的,我知道这不是一个好主意)。这给了我正确的总数,但描述没有准确反映,例如有些记录应该是“保险”,而是显示“发货”。

2 个答案:

答案 0 :(得分:5)

最简单的方法是编写两个查询并将结果联合起来

select <columns>
where description not in('Insurance','Pickup')
group by  <some columns)
union all
select <columns>
where description in('Insurance','Pickup')

答案 1 :(得分:0)

也许是这样的:

SELECT
  customerName,
  quoteID,
  description = CASE
    WHEN description IN ('Insurance', 'Pickup') THEN description
    ELSE 'Shipment'
  END,
  shippingCharges = SUM(shippingCharges)
FROM quotes q
  INNER JOIN customers c ON q.customerID = c.customerID
GROUP BY
  customerName,
  quoteID,
  CASE
    WHEN description IN ('Insurance', 'Pickup') THEN description
    ELSE 'Shipment'
  END

你一定注意到这里重复了两次相同的CASE表达式。您可以使用普通的子选择来避免它:

SELECT
  customerName,
  quoteID,
  description,
  shippingCharges = SUM(shippingCharges)
FROM (
  SELECT
    customerName,
    quoteID,
    description = CASE
      WHEN description IN ('Insurance', 'Pickup') THEN description
      ELSE 'Shipment'
    END,
    shippingCharges = SUM(shippingCharges)
  FROM quotes q
    INNER JOIN customers c ON q.customerID = c.customerID
) s
GROUP BY
  customerName,
  quoteID,
  description

或CTE:

WITH preparedList AS (
  SELECT
    customerName,
    quoteID,
    description = CASE
      WHEN description IN ('Insurance', 'Pickup') THEN description
      ELSE 'Shipment'
    END,
    shippingCharges = SUM(shippingCharges)
  FROM quotes q
    INNER JOIN customers c ON q.customerID = c.customerID
)
SELECT
  customerName,
  quoteID,
  description,
  shippingCharges = SUM(shippingCharges)
FROM preparedList
GROUP BY
  customerName,
  quoteID,
  description

您可能还需要根据需要添加其他一些列。