我已经创建了一个查询。在该查询中,有一些表连接到另一个表 table.I m直接获取列ContactId,FirstName,LastName,CreatedOn的值。 对于paymnettype列,我正在解析P.new_name中的值(值类似于'Credit Card - 2014-06-29')。对于paymenttype,'Credit Card'和'Miles Point'有2种类型的值
我在该查询中的主要目的是获得每个联系人的航班预订利润的总和,这就是为什么我要按除totalamount列之外的所有列对表进行分组 聚合函数work.I m按paytype对表进行分组,因为我必须这样做,否则它会按预期给出错误。
问题在于,如果联系人在两种付款方式中进行了预订,那么contactid将显示在两列中。
我希望将其显示在一列中,在查询中像往常一样获取总和并在paymenttype列中写入“all”。 这是可能的。如果是的话,任何关于我如何做到这一点的想法。
另外我应该提一下,我会在SSRS中使用该查询,所以解决SSRS方面问题的任何想法都会对我有帮助
Select C.ContactId,C.FirstName,C.LastName,C.CreatedOn,
LTRIM(RTRIM(left(P.new_name ,(CHARINDEX('-',P.new_name)-1))))) as paymenttype,
SUM(F.new_totalamounttl) as totalamount
From Contact C
left join SalesOrder S on C.ContactId=S.ContactId
left join new_flightreservation F on S.SalesOrderId=F.new_salesorderid
left join new_payment P on F.new_paymentid=P.new_paymentId
where
(LTRIM(RTRIM(left(P.new_name ,(CHARINDEX('-',P.new_name)-1))))) IN
( CASE @paymenttype WHEN 'all'
THEN (LTRIM(RTRIM(left(P.new_name ,(CHARINDEX('-',P.new_name)-1)))))
ELSE @paymenttype END )
GROUP BY C.ContactId,C.FirstName,C.LastName,C.CreatedOn,
(LTRIM(RTRIM(left(P.new_name ,(CHARINDEX('-',P.new_name)-1)))))
答案 0 :(得分:2)
我认为通过将其分为两部分,您可以获得相当优雅的解决方案。第一部分处理PaymentType,第二部分基于此进行分组/求和。
SELECT
ContactId
,FirstName
,LastName
,CreatedOn
,SUM(subamount) totalamount
,paymenttype
FROM
(
Select
C.ContactId
,C.FirstName
,C.LastName
,C.CreatedOn
,@paymenttype as paymenttype
,CASE
WHEN @paymenttype = ‘all’ THEN F.new_totalamounttl
WHEN @paymenttype = LTRIM(RTRIM(LEFT(P.new_name ,(CHARINDEX('-',P.new_name)-1))))) THEN F.new_totalamounttl
ELSE 0 END as subamount
From
Contact C
left join SalesOrder S
on C.ContactId=S.ContactId
left join new_flightreservation F
on S.SalesOrderId=F.new_salesorderid
left join new_payment P
on F.new_paymentid=P.new_paymentId
) sub
GROUP BY
ContactId
,FirstName
,LastName
,CreatedOn
,paymenttype
答案 1 :(得分:1)
注意事项:这个解决方案非常难看,但我认为它有效(可能性能很差)。我还在考虑一种更好的方法。
让我们将解析与连接隔离开来,这样完整的查询将更容易理解;我们也会将Contact
放在一边,因为最后可以加入任何ContactId
值以获取完整的Contact
详细信息。请注意,既没有分组也没有汇总功能:
Select
S.ContactId,
LTRIM(RTRIM(left(P.new_name ,(CHARINDEX('-',P.new_name)-1)))) as paymenttype,
F.new_totalamounttl as totalamount
From
SalesOrder S
left join new_flightreservation F on S.SalesOrderId=F.new_salesorderid
left join new_payment P on F.new_paymentid=P.new_paymentId
上面的子查询“生成”(虽然没有具体化)每个预订每个订单每行订单一行,并解析付款名称(如果您的数据库已规范化,这将是不必要的)。由于每个订单属于一个联系人,因此也是每次联系。
现在我们按@paymenttype过滤:
SELECT *
FROM (
Select
S.ContactId,
LTRIM(RTRIM(left(P.new_name ,(CHARINDEX('-',P.new_name)-1)))) as paymenttype,
F.new_totalamounttl as totalamount
From
SalesOrder S
left join new_flightreservation F on S.SalesOrderId=F.new_salesorderid
left join new_payment P on F.new_paymentid=P.new_paymentId
) AS x
WHERE
@paymenttype = x.paymenttype OR @paymenttype = 'all'
-- alternatively in some databases (rather ugly, but concise):
-- @paymenttype IN (x.paymenttype, 'all')
这反过来被视为一个匿名视图(我将在下面的评论中称之为“A”)在下一个查询中,有两个分支:第一个将收集其支付类型完全相同的行(即没有其他类型的付款);另一个分支将收集其他行(每个订单的不同付款类型)。这次我们已经汇总了已支付的金额。
-- 1st branch
SELECT y.ContactId, y.paymenttype, SUM(y.totalamount) AS totalamount
FROM (
-- the view A
SELECT *
FROM (
Select
S.ContactId,
LTRIM(RTRIM(left(P.new_name ,(CHARINDEX('-',P.new_name)-1)))) as paymenttype,
F.new_totalamounttl as totalamount
From
SalesOrder S
left join new_flightreservation F on S.SalesOrderId=F.new_salesorderid
left join new_payment P on F.new_paymentid=P.new_paymentId
) AS x
WHERE
x.paymenttype = @paymenttype OR @paymenttype = 'all'
) AS y
WHERE
NOT EXISTS (
SELECT *
FROM (
-- the view A (again)
SELECT *
FROM (
Select
S.ContactId,
LTRIM(RTRIM(left(P.new_name ,(CHARINDEX('-',P.new_name)-1)))) as paymenttype,
F.new_totalamounttl as totalamount
From
SalesOrder S
left join new_flightreservation F on S.SalesOrderId=F.new_salesorderid
left join new_payment P on F.new_paymentid=P.new_paymentId
) AS x
WHERE
x.paymenttype = @paymenttype OR @paymenttype = 'all'
) AS y1
WHERE y.ContactId = y1.ContactId
AND y.paymenttype <> y1.paymenttype
)
GROUP BY y.ContactId, y.paymenttype
UNION ALL
-- 2nd branch
SELECT y.ContactId, 'all' AS paymenttype, SUM(y.totalamount) AS totalamount
FROM (
-- the view A
SELECT *
FROM (
Select
S.ContactId,
LTRIM(RTRIM(left(P.new_name ,(CHARINDEX('-',P.new_name)-1)))) as paymenttype,
F.new_totalamounttl as totalamount
From
SalesOrder S
left join new_flightreservation F on S.SalesOrderId=F.new_salesorderid
left join new_payment P on F.new_paymentid=P.new_paymentId
) AS x
WHERE
x.paymenttype = @paymenttype OR @paymenttype = 'all'
) AS y
WHERE
EXISTS (
SELECT *
FROM (
-- the view A (again)
SELECT *
FROM (
Select
S.ContactId,
LTRIM(RTRIM(left(P.new_name ,(CHARINDEX('-',P.new_name)-1)))) as paymenttype,
F.new_totalamounttl as totalamount
From
SalesOrder S
left join new_flightreservation F on S.SalesOrderId=F.new_salesorderid
left join new_payment P on F.new_paymentid=P.new_paymentId
) AS x
WHERE
x.paymenttype = @paymenttype OR @paymenttype = 'all'
) AS y1
WHERE y.ContactId = y1.ContactId
AND y.paymenttype <> y1.paymenttype
)
GROUP BY y.ContactId
现在到最后查询,恢复Contact
详细信息。上面的查询被视为匿名视图以简化连接:
Select C.ContactId,C.FirstName,C.LastName,C.CreatedOn,
z.paymenttype, z.totalamount
From Contact C
left join (
-- 1st branch
SELECT y.ContactId, y.paymenttype, SUM(y.totalamount) AS totalamount
FROM (
-- the view A
SELECT *
FROM (
Select
S.ContactId,
LTRIM(RTRIM(left(P.new_name ,(CHARINDEX('-',P.new_name)-1)))) as paymenttype,
F.new_totalamounttl as totalamount
From
SalesOrder S
left join new_flightreservation F on S.SalesOrderId=F.new_salesorderid
left join new_payment P on F.new_paymentid=P.new_paymentId
) AS x
WHERE
x.paymenttype = @paymenttype OR @paymenttype = 'all'
) AS y
WHERE
NOT EXISTS (
SELECT *
FROM (
-- the view A (again)
SELECT *
FROM (
Select
S.ContactId,
LTRIM(RTRIM(left(P.new_name ,(CHARINDEX('-',P.new_name)-1)))) as paymenttype,
F.new_totalamounttl as totalamount
From
SalesOrder S
left join new_flightreservation F on S.SalesOrderId=F.new_salesorderid
left join new_payment P on F.new_paymentid=P.new_paymentId
) AS x
WHERE
x.paymenttype = @paymenttype OR @paymenttype = 'all'
) AS y1
WHERE y.ContactId = y1.ContactId
AND y.paymenttype <> y1.paymenttype
)
GROUP BY y.ContactId, y.paymenttype
UNION ALL
-- 2nd branch
SELECT y.ContactId, 'all' AS paymenttype, SUM(y.totalamount) AS totalamount
FROM (
-- the view A
SELECT *
FROM (
Select
S.ContactId,
LTRIM(RTRIM(left(P.new_name ,(CHARINDEX('-',P.new_name)-1)))) as paymenttype,
F.new_totalamounttl as totalamount
From
SalesOrder S
left join new_flightreservation F on S.SalesOrderId=F.new_salesorderid
left join new_payment P on F.new_paymentid=P.new_paymentId
) AS x
WHERE
x.paymenttype = @paymenttype OR @paymenttype = 'all'
) AS y
WHERE
EXISTS (
SELECT *
FROM (
-- the view A (again)
SELECT *
FROM (
Select
S.ContactId,
LTRIM(RTRIM(left(P.new_name ,(CHARINDEX('-',P.new_name)-1)))) as paymenttype,
F.new_totalamounttl as totalamount
From
SalesOrder S
left join new_flightreservation F on S.SalesOrderId=F.new_salesorderid
left join new_payment P on F.new_paymentid=P.new_paymentId
) AS x
WHERE
x.paymenttype = @paymenttype OR @paymenttype = 'all'
) AS y1
WHERE y.ContactId = y1.ContactId
AND y.paymenttype <> y1.paymenttype
)
GROUP BY y.ContactId
) AS z on C.ContactId=z.ContactId
答案 2 :(得分:1)
借鉴my previous (and hackish) answer的想法,我可以设计以下(甚至更简洁,但更简洁)解决方案:
SELECT C.ContactId,C.FirstName,C.LastName,C.CreatedOn,
CASE
WHEN (
COUNT(CASE x.paymenttype WHEN 'Credit Card' THEN 1 ELSE NULL END)
* COUNT(CASE x.paymenttype WHEN 'Miles Point' THEN 1 ELSE NULL END)
) > 0 THEN 'all'
WHEN COUNT(CASE x.paymenttype WHEN 'Credit Card' THEN 1 ELSE NULL END) > 0 THEN 'Credit Card'
ELSE 'Miles Point'
END AS paymenttype,
SUM(F.new_totalamounttl) AS totalamount
FROM
Contact C
left join SalesOrder S on C.ContactId=S.ContactId
left join new_flightreservation F on S.SalesOrderId=F.new_salesorderid
left join (
Select
P.new_paymentId,
LTRIM(RTRIM(left(P.new_name ,(CHARINDEX('-',P.new_name)-1)))) as paymenttype,
From new_payment P
) AS x on F.new_paymentid=x.new_paymentId
WHERE @paymenttype = x.paymenttype OR @paymenttype = 'all'
-- alternatively, for the RDBMS that allows it:
-- @paymenttype IN (x.paymenttype, 'all')
GROUP BY C.ContactId,C.FirstName,C.LastName,C.CreatedOn
编辑:稍微简化了查询以避免一个额外的匿名视图