我在SQL Server 2008中运行查询..我有一个sales
表和一个payments
表..有时销售有多种付款方式(部分礼品卡+部分现金或部分信用卡) +部分现金等..)所以我想要做的是在表格中列出每笔销售的销售和付款。
如果我执行LEFT JOIN ON sales.SaleID = payments.SaleID
,当有多个匹配的付款行时,我会获得重复的销售行数。
所以我一直在做的是获取所有销售额以及与(SELECT COUNT(*) FROM payments WHERE payments.SaleID = sales.SaleID) AS NumOfPayments
匹配的付款行数。然后在我的PHP脚本中,我检查付款的数量,如果是> 1
我然后运行另一个查询来获取付款详细信息。
我想要的输出看起来像这样
-----------------------------------------------------
| SaleID | SaleDate | Amount | Payments |
-----------------------------------------------------
| 123 | 2013-07-23 | $ 19.99 | Cash: $ 19.99 |
| 124 | 2013-07-23 | $ 7.53 | Cash: $ 7.53 |
| 125 | 2013-07-23 | $174.30 | Credit: $124.30 |
| | | | GiftCard: $ 50.00 |
| 126 | 2013-07-23 | $ 79.99 | Cash: $ 79.99 |
| 127 | 2013-07-23 | $100.00 | Credit: $ 90.00 |
| | | | Cash: $ 10.00 |
-----------------------------------------------------
如果销售125和127有多个付款列出,但销售信息只出现一次,并且每次付款都不重复。
sales
和payments
表格如下所示:
Sales Payments
--------------------------------- --------------------------------------------
| SaleID | SaleDate | Amount | | PaymentID | SaleID | PmtMethod | PmtAmt |
--------------------------------- --------------------------------------------
| 123 | 2013-07-23 | $ 19.99 | | 158 | 123 | 4 | $ 19.99 |
| 124 | 2013-07-23 | $ 7.53 | | 159 | 124 | 4 | $ 7.53 |
| 125 | 2013-07-23 | $174.30 | | 160 | 125 | 2 | $124.30 |
| 126 | 2013-07-23 | $ 79.99 | | 161 | 125 | 3 | $ 50.00 |
| 127 | 2013-07-23 | $100.00 | | 162 | 126 | 4 | $ 79.99 |
--------------------------------- | 163 | 127 | 2 | $ 90.00 |
| 164 | 127 | 4 | $ 10.00 |
--------------------------------------------
我觉得如果我能用SQL做它会更快。有没有办法用纯SQL实现这一点,而不必使用服务器端代码来运行条件查询。
答案 0 :(得分:1)
我不会混合数据检索和数据显示,这是我认为你在问的问题。您是否有某种列表明应首先显示哪些付款?我想的是:
SELECT columnlist,
rn = ROW_NUMBER() OVER (PARTITION BY sales.salesID ORDER BY payment.paymentID)
FROM sales JOIN payments ON sales.salesID=payments.salesID
然后,在您的GUI中,只显示RN = 1的前3列的值,并删除RN> 1的值。 1。
答案 1 :(得分:0)
在界面中执行此操作可能更容易。
您想要的基本查询是:
select s.saleID, s.SaleDate, s.Amount,
p.PaymentType, p.PaymentAmount,
ROW_NUMBER() over (partition by p.SaleId order by p.PaymentAmount desc) as seqnum
from sales s join
payments p
on p.saleID = s.saleId
order by 1, 2
但是,您正在尝试删除字段。为此,您需要将所有字段转换为字符串,然后检查每个SaleId
的第一行中是哪一个:
select (case when seqnum > 1 then '' else CAST(SaleId as varchar(255)) end) as SaleId,
(case when seqnum > 1 then '' else CONVERT(varchar(10), SaleDate, 121) end) as SaleDate,
(case when seqnum > 1 then '' else '$'+STR(amount, 6, 2) end) as Amount,
PaymentType, PaymentAmount
from (select s.saleID, s.SaleDate, s.Amount,
p.PaymentType, p.PaymentAmount,
ROW_NUMBER() over (partition by p.SaleId order by p.PaymentAmount desc) as seqnum
from sales s join
payments p
on p.saleID = s.saleId
) sp
order by SaleId, SaleDate;
这不是SQL的设计类型。 SQL与表一起使用,其中所有列具有相同的含义。在这里,您将根据其在销售中的位置为该列引入不同的含义。是的,SQL可以做到。不,这不容易。
答案 2 :(得分:0)
以下查询将提供您需要的结果,您需要跳过SalesIDToSort列。
;with SalesData
as
(
select
Sales.SalesID, Sales.SalesDate, Sales.TotalAmount, Payments.PaymentMode, Payments.Amount,
Row_Number() over(Partition by Sales.SalesID order by Payments.PaymentID) RowNum
from
Payments
inner join Sales on Payments.SalesID = Sales.SalesID
)
select SalesID, SalesDate, TotalAmount, PaymentMode, Amount, SalesID SalesIDToSort
from
SalesData
where
SalesData.RowNum = 1
union all
select null, null, null, PaymentMode, Amount, SalesID SalesIDToSort
from
SalesData
where
SalesData.RowNum > 1
order by 6
答案 3 :(得分:0)
您可以按照格式的功能尝试分组:
select salesid, salesDate, Amount, FORMAT(payment, 9999.999) as payments
from FROM payments
WHERE payments.SaleID = sales.SaleID
group by salesid;
如果您将FORMAT作为可用功能,这可能会有效。