我有一个客户表和一个订单表。我想将客户及其所有订单日期显示在一行上,而不是多行上。这是我所拥有的以及正在寻找的东西:
获得结果的基本代码:
select customerid, name, orderdate
from customer_table c inner join
order_table o
on c.customerid = o.customerid
答案 0 :(得分:1)
这将最多发挥您无法在具有null的不同列上显示它的作用:
select customer_id,name,LISTAGG(orderdate, ', ') WITHIN GROUP (ORDER BY orderdate)
from(select customerid, name, orderdate
from customer_table c inner join
order_table o
on c.customerid = o.customerid );
答案 1 :(得分:0)
如果使用MS SQL Server,请尝试以下操作:
-- 1st, get the number of columns
declare @columnnumber int = 1
select @columnnumber = max(a.count)
from (
select c.cid,c.name, count(o.orderdate) as count
from
customer_table c
join order_table o
on c.cid = o.cid
group by c.cid,c.name)a
print @columnnumber
-- Compose the column names for Pivot
declare @columnname varchar(max) = ''
declare @int int = 1
while @int <= @columnnumber
begin
set @columnname = @columnname + '[date' + cast(@int as varchar(10))+ '],'
set @int = @int + 1
end
set @columnname = '('+left(@columnname,len(@columnname)-1)+')'
print @columnname
--Pivot !!! + Dynamic SQL
declare @str varchar(max)
set @str =
'SELECT *
FROM
(SELECT c.cid,c.name, o.orderdate,concat(''date'',row_number() over (partition by c.cid,c.name order by o.orderdate)) rnk
FROM customer_table c
join order_table o
on c.cid = o.cid) AS s
PIVOT
(
min(s.orderdate)
FOR s.rnk IN '+ @columnname+
' ) AS PivotTable'
print @str
execute (@str)
请更改列名称。我使用cid作为您的客户ID。
输出:
cid name date1 date2 date3
12 John 2017-03-04 2017-05-26 2017-12-01
4 Nancy 2017-02-01 NULL NULL
答案 2 :(得分:0)
您可以使用以下内容,因为您受12个订单限制的约束。如果您扩展到无上限的未知数量的订单,那么您将需要使用动态SQL,即使那样也很棘手,因为您还需要动态创建唯一的列名。
此查询按客户进行批处理并设置订单值。它们将按日期顺序排列,如果没有更多订单,则将其设置为NULL。它有点假设至少一个客户有12个订单。如果不是这种情况,您将获得所有NULL的列
IF OBJECT_ID('tempdb..#Results') IS NOT NULL DROP TABLE #Results
IF OBJECT_ID('tempdb..#sortedRows') IS NOT NULL DROP TABLE #SortedRows
DECLARE @CustomerList TABLE(CustomerID INT, RowNo INT);
INSERT INTO @CustomerList SELECT DISTINCT CustomerID, ROW_NUMBER() OVER(ORDER BY CustomerID) RowNo FROM Customer_Table (NOLOCK)
DECLARE @Count INT = (SELECT COUNT(DISTINCT CustomerID) RowNumber FROM @CustomerList)
DECLARE @Counter INT = 0
DECLARE @CustToProcess INT
CREATE TABLE #Results(CustomerID INT, [Name] VARCHAR(50), OrderDate1 DATETIME,
OrderDate2 DATETIME, OrderDate3 DATETIME, OrderDate4 DATETIME, OrderDate5 DATETIME,
OrderDate6 DATETIME, OrderDate7 DATETIME, OrderDate8 DATETIME, OrderDate9 DATETIME,
OrderDate10 DATETIME, OrderDate11 DATETIME, OrderDate12 DATETIME)
INSERT INTO #Results(CustomerID, Name) SELECT DISTINCT CustomerID, Name FROM Customer_Table
SELECT ROW_NUMBER() OVER(PARTITION BY c.CustomerID ORDER BY OrderDate) RowNo,
c.CustomerID, c.Name, t.OrderDate INTO #SortedRows
FROM Customer_Table c (NOLOCK) JOIN Order_Table t ON c.CustomerID = t.CustomerID
WHILE @Counter < @Count
BEGIN
SET @Counter += 1
SET @CustToProcess = (SELECT CustomerID FROM @CustomerList WHERE RowNo = @Counter)
PRINT @CustToProcess
SELECT * INTO #RowsForProcessing FROM #SortedRows WHERE CustomerID = @CustToProcess
UPDATE #Results SET OrderDate1 = (SELECT OrderDate FROM #RowsForProcessing WHERE Rowno = 1) WHERE CustomerID = @CustToProcess
UPDATE #Results SET OrderDate2 = (SELECT OrderDate FROM #RowsForProcessing WHERE Rowno = 2) WHERE CustomerID = @CustToProcess
UPDATE #Results SET OrderDate3 = (SELECT OrderDate FROM #RowsForProcessing WHERE Rowno = 3) WHERE CustomerID = @CustToProcess
UPDATE #Results SET OrderDate4 = (SELECT OrderDate FROM #RowsForProcessing WHERE Rowno = 4) WHERE CustomerID = @CustToProcess
UPDATE #Results SET OrderDate5 = (SELECT OrderDate FROM #RowsForProcessing WHERE Rowno = 5) WHERE CustomerID = @CustToProcess
UPDATE #Results SET OrderDate6 = (SELECT OrderDate FROM #RowsForProcessing WHERE Rowno = 6) WHERE CustomerID = @CustToProcess
UPDATE #Results SET OrderDate7 = (SELECT OrderDate FROM #RowsForProcessing WHERE Rowno = 7) WHERE CustomerID = @CustToProcess
UPDATE #Results SET OrderDate8 = (SELECT OrderDate FROM #RowsForProcessing WHERE Rowno = 8) WHERE CustomerID = @CustToProcess
UPDATE #Results SET OrderDate9 = (SELECT OrderDate FROM #RowsForProcessing WHERE Rowno = 9) WHERE CustomerID = @CustToProcess
UPDATE #Results SET OrderDate10 = (SELECT OrderDate FROM #RowsForProcessing WHERE Rowno = 10) WHERE CustomerID = @CustToProcess
UPDATE #Results SET OrderDate11 = (SELECT OrderDate FROM #RowsForProcessing WHERE Rowno = 11) WHERE CustomerID = @CustToProcess
UPDATE #Results SET OrderDate12 = (SELECT OrderDate FROM #RowsForProcessing WHERE Rowno = 12) WHERE CustomerID = @CustToProcess
DROP Table #RowsForProcessing
END
SELECT * FROM #Results
答案 3 :(得分:0)
就像其他人说的那样,原则上(纯SQL)不可能不知道单个客户有多少订单就生成此信息。
我喜欢@ nikhil-sugandh的回答,如果您可以将所有订单用逗号分隔在一个列中,那么效果很好。
如果您坚持要有多列,则可以通过用LISTAGG
替换ARRAY_AGG
并对其进行后处理来建立答案。它将比例如带有多个联接的建议解决方案。您还可以使用ARRAY_SLICE
处理订单数量超出您准备的情况。
示例(注意,我添加了一个额外的订单,以演示如何处理超出预期的订单
create or replace table customer_table(customerId int, name varchar)
as select * from values
(12,'John'),(4,'Nancy');
create or replace table order_table(orderId int, customerId int, orderDate date)
as select * from values
(1,12,'3/4/2017'),(2,12,'5/26/2017'),(3,12,'12/1/2017'),(4,4,'2/1/2017'),(5,12,'1/1/2019');
with subq as (
select c.customerid, name,
array_agg(orderdate) within group (order by orderdate) as orders
from customer_table c
inner join order_table o on c.customerid = o.customerid
group by c.customerid, c.name
)
select customerid, name,
orders[0]::date AS order1, orders[1]::date AS order2,
array_to_string(array_slice(orders, 2, 999), ' , ') AS overflow
from subq;
------------+-------+------------+------------+-------------------------+
CUSTOMERID | NAME | ORDER1 | ORDER2 | OVERFLOW |
------------+-------+------------+------------+-------------------------+
4 | Nancy | 2017-02-01 | [NULL] | |
12 | John | 2017-03-04 | 2017-05-26 | 2017-12-01 , 2019-01-01 |
------------+-------+------------+------------+-------------------------+
答案 4 :(得分:-1)
首先创建一个这样的视图:
create view order_view as
select
count(*) over (partition by customerId order by orderDate) as ord,
CustomerId,
orderdate
from order_table
然后您可以使用以下查询:
select c.customerid,
o1.orderdate,
o2.orderdate
o3.orderdate
.
.
.
o12.orderdate
from customer_table c
left join order_view o1
on c.customerid = o1.customerid and ord = 1
left join order_view o2
on c.customerid = o2.customerid and ord = 2
left join order_view o3
on c.customerid = o3.customerid and ord = 3
.
.
.
left join order_view o12
on c.customerid = o12.customerid and ord = 12