2013-07-23 40 views
0

我在SQL Server 2008中运行查询..我有一个sales表和一个payments表..有时销售有多种付款方式(部分礼品卡+零件现金或零件信用+部分现金等)。所以我想要做的是在表格中列出每笔销售的销售额和付款。SQL查询一对多关系连接无重复

如果我做了我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来实现,而不必使用服务器端代码来运行条件查询。

+0

所有销售额在支付表中至少有一个记录,对吗? – Vasanth

+0

@VasanthSundaralingam是的每个销售至少应该有一个相应的付款记录 –

回答

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,只显示值第3列,其中RN = 1,并空出的值,其中RN> 1

+0

我已经使用mysql 5.6这种方法,它给了我惊人的具体信息“你有一个SQL语法错误”:( – danba

+0

MySQL不是SQL服务器:)我不认为MySQL支持ROW_NUMBER()功能。 –

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

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 

Working demo

0

您可以尝试通过功能gourp等业态于:

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

,如果您有格式作为可用的功能,这可能工作。