0

我在 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 列出了多笔付款,但销售信息只出现一次,并且每次付款不重复。

和表如下所示salespayments

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 来实现这一点,而不必使用服务器端代码来运行条件查询。

4

4 回答 4

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 的值。

于 2013-07-23T19:01:04.183 回答
1

在界面中执行此操作可能更容易。

您想要的基本查询是:

  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 可以做到。不,这并不容易。

于 2013-07-23T19:06:46.410 回答
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

工作演示

于 2013-07-23T19:11:21.527 回答
0

您可以尝试按功能(例如 Format )进行搜索:

select salesid, salesDate, Amount, FORMAT(payment, 9999.999) as payments
from FROM payments 
WHERE payments.SaleID = sales.SaleID
group by salesid;

如果您将 FORMAT 作为可用功能,这可能会起作用。

于 2013-07-23T19:40:24.760 回答