2015-07-20 75 views
0

我曾在Stackoverflow上看到过几个类似的问题,但是这并不适合所有这些问题。将行显示为列

我有3个表购买,酒店,汽车购买酒店和汽车是1比0或许多关系。 MS SQL 2008服务器。

采购表

pid bookingdate ... 
1 
2 
3 

酒店表

hid pid amount rooms location brand... 
1 1 
2 1 
3 1 
4 3 
4 3 

车表

cid pid make model ... 
1 1 
2 2 
3 2 

我要的是显示在列的酒店数据

pid bookingdate cid make model hid1 amount1 rooms1 location1 brand1 hid2 amount2 rooms2 location2 brand2 hid3 amount3 rooms3 location3 brand3 hid4 amount4 rooms4 location4 brand4 

如果给定购买ID只有一家酒店,则其他列应为空。如果超过4家酒店忽略其他酒店(第六第六等)

请假设车台在这个阶段可以有0或1。

(提前:: >>如果汽车能表0到很多(关系购买)1)只取第一条记录占2)获得记录的总和。)

目的本项目是生成一个可以上传到某个第三方产品的csv文件。目前,我们有大约100列购买和汽车约30列酒店(130全部)。随着酒店行以这种方式显示,它将是220(100 + 30 x 4)列。约100K行。性能也是一个问题。

我尝试了一些东西,但没有成功,甚至没有接近卡住。 This是我得到的最接近的,但我有30列复制不只是一个,事实上,我有一种感觉,PIVOT是不是要走的路。我使用DENSE_RANK()或类似的

SELECT pid 
, hid 
, DENSE_RANK() OVER(ORDER BY pid) 
FROM HOTEL 
WHERE pid IN ( 
       SELECT pid 
       FROM Hotel 
       WHERE pid IN (
          SELECT pid 
          FROM Purchase 
          WHERE rdate BETWEEN '2014-04-01' AND '2014-12-31' 
          ) 
       GROUP BY pid 
       HAVING COUNT(pid) > 1 
      ) 

假设那么我们可能能够与附着在一起的第一购买超过1处理酒店,使用光标(丑陋的)或类似的东西

+0

你试过了什么?你可以向你展示查询和你在哪堆栈? – Fabio

+0

我尝试了一些东西,但没有成功,甚至没有接近卡住。 http://sqlfiddle.com/#!3/832f1/16是我得到的最接近的,但我有30列复制不只是一个,事实上,我有一种感觉,PIVOT是不是要走的路。我使用DENSE_RANK()或类似的东西'选择PID OVER(ORDER BY PID) 思考,HID,DENSE_RANK()从酒店 WHERE PID IN(SELECT PID从酒店 其中PID IN(SELECT PID自购买WHERE rdate BETWEEN'2014-04-01'和'2014-12-31' ) GROUP BY pid HAVING COUNT(pid)> 1)' – Udaan

回答

0

好吧我找到了解决方案。欢迎您完善并添加您的想法。动态命名列会很方便。 (即产品1,产品2,产品3,产品4)

架构

create table Purchase 
(
    pid int, 
    purchasedate date, 
    currency varchar(10), 
    paymenttype varchar(10), 
    creditcard varchar(10), 
    creditcardtype varchar(10) 
); 

create table Hotel 
(
    hid int, 
    pid int, 
    product varchar(30), 
    country varchar(10), 
    city varchar(10), 
    rooms int, 
    starrating int 
); 

create table Car 
(
    cid int, 
    pid int, 
    product varchar(30), 
    country varchar(10), 
    city varchar(10), 
    cancel int, 
    starrating int 
); 


insert into Purchase values (1, '2015-01-15','AUD', 'CC','12345678','AMEX') 
insert into Purchase values (2, '2015-01-15','AUD', 'CC','12345678','AMEX') 
insert into Purchase values (3, '2015-01-15','AUD', 'CC','12345678','AMEX') 
insert into Purchase values (4, '2015-01-15','AUD', 'CC','12345678','AMEX') 
insert into Purchase values (5, '2015-01-15','AUD', 'CC','12345678','AMEX') 


insert into Hotel values (1,1, 'Five for Two','Australia', 'Melbourne','1','3') 
insert into Hotel values (2,1, 'Five for None','Australia', 'Sydney','1','3') 
insert into Hotel values (3,1, 'Five for Five','Australia', 'Melbourne','1','3') 
insert into Hotel values (4,1, 'Five for Two','Australia', 'Jamboora','1','3') 
insert into Hotel values (5,2, 'Five for Three','Australia', 'Sydney','1','3') 
insert into Hotel values (6,2, 'Five for Love','Australia', 'Cook','1','3') 
insert into Hotel values (7,2, 'Five for Grease','Australia', 'Darwin','1','3') 
insert into Hotel values (8,3, 'Love Me','Australia', 'Darwin','1','3') 
insert into Hotel values (9,4, 'Live for Grease','Australia', 'Footscray','1','3') 
insert into Hotel values (10,4, 'Love Grease','Australia', 'Officer','1','3') 

insert into Car values (1,1, 'Love Grease','Australia', 'Officer','1','3') 
insert into Car values (2,2, 'Love Grease','Australia', 'Cook','1','3') 
insert into Car values (3,4, 'Live Grease','Australia', 'Jamboora','1','3') 
-- For Advance insert into Car values (4,4, 'Cove Grease','Australia', 'Melbourne','1','3') 

而且代码

SELECT *, DENSE_RANK() OVER(PARTITION BY pid ORDER BY hid DESC) AS Ranking 
INTO #TempHotel 
FROM Hotel 

SELECT P.pid, P.purchasedate, P.currency, P.paymenttype, P.creditcard, P.creditcardtype 
    ,C.cid, C.product, C.country, C.city, C.cancel, C.starrating 
    ,H1.hid, H1.product, H1.country, H1.city,H1.rooms,H1.starrating 
    ,H2.hid, H2.product, H2.country, H2.city,H2.rooms,H2.starrating 
    ,H3.hid, H3.product, H3.country, H3.city,H3.rooms,H3.starrating 
    ,H4.hid, H4.product, H4.country, H4.city,H4.rooms,H4.starrating 
FROM Purchase P 
left join Car C on P.pid = C.pid 
left join #TempHotel H1 on P.pid = H1.pid and H1.Ranking = 1 
left join #TempHotel H2 on P.pid = H2.pid and H2.Ranking = 2 
left join #TempHotel H3 on P.pid = H3.pid and H3.Ranking = 3 
left join #TempHotel H4 on P.pid = H4.pid and H4.Ranking = 4 
DROP Table #TempHotel 

您还可以在SQL小提琴Here找到。

-1

如果想的东西列数永远不会改变,你可以使用数据透视/逆透视

这里是一个TechNet文章它说明了一切:http://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx

,并从文章的样本。

-- Pivot table with one row and five columns 
SELECT 'AverageCost' AS Cost_Sorted_By_Production_Days, 
[0], [1], [2], [3], [4] 
FROM 
(SELECT DaysToManufacture, StandardCost 
    FROM Production.Product) AS SourceTable 
PIVOT 
(
AVG(StandardCost) 
FOR DaysToManufacture IN ([0], [1], [2], [3], [4]) 
) AS PivotTable; 
+0

对投票的解释将不胜感激。 – Wombelite

+0

我不需要平均或总和。我之前看过这个解决方案。我不确定我们是否可以在这种情况下使用PIVOT,顺便说一句,我没有把它标出来 – Udaan