Hello T-SQL社区
我有一个项目,我需要在星期一结束时交付。因为我已经用尽所有其他形式的研究,我迫切需要你的帮助!
我想做的是如下
返回将表1转换为表2的数据集
表1:
def parse(self, response):
for sel in response.xpath('//table[@class]/tbody/tr'):
item = SET()
item['title'] = sel.xpath('td[1]/a[contains(@href,"ssoPageId")]/text()').extract()
item['open'] = sel.xpath('td[3]/text()').extract()
item['hi'] = sel.xpath('td[4]/text()').extract()
item['lo'] = sel.xpath('td[5]/text()').extract()
item['last'] = sel.xpath('td[6]/text()').extract()
item['bid'] = sel.xpath('td[9]/text()').extract()
item['ask'] = sel.xpath('td[10]/text()').extract()
item['vol'] = sel.xpath('td[11]/text()').extract()
urll = response.xpath('//table[@class]/tbody/tr/td[1]/a[contains(@href,"ssoPageId")]/@href').extract()
urls = ["http://marketdata.set.or.th/mkt/" + i for i in urll]
for url in urls:
yield scrapy.Request(url,
callback=self.parse_following_urls,
meta={'item': item})
对此...
表2:
Customer_No Name Telephone_No Address Street_Name Postcode
=========== ==== ============ ========= =========== ========
635532 Mr X 0771111111 FLAT 1000 BEACH ROAD BN23 5HT
635532 Mr X 0771112222 FLAT 1000 BEACH ROAD BN23 5HT
635532 Mr X 01903773333 FLAT 1000 BEACH ROAD BN23 5HT
635532 Mr X 01903774444 FLAT 1000 BEACH ROAD BN23 5HT
每位客户最多可以有10个电话号码。
为清楚起见,上图显示在附图中
这是我目前建立的查询,但它受到我硬编码的电话字段数量的限制。我希望动态构建列
Customer_No Name Telephone_No_1 Telephone_No_2 Telephone_No_3 Telephone_No_4 Address Street_Name Postcode
=========== ==== ============== ============== ============== ============== ========= =========== ========
635532 Mr X 0771111111 0771112222 01903773333 01903774444 FLAT 1000 BEACH ROAD BN23 5HT
我将非常感谢你对此的帮助。
非常感谢!
答案 0 :(得分:4)
假设您正在使用SQL-Server 2012及更高版本
创建样本数据:
CREATE TABLE #temp (Customer_No INT, Name VARCHAR(100), Telephone_No VARCHAR(100), Address VARCHAR(100), Street_Name VARCHAR(100), Postcode VARCHAR(100))
INSERT INTO #temp
VALUES
(635532,'Mr X','0771111111','FLAT 1000','BEACH ROAD','BN23 5HT'),
(635532,'Mr X','0771112222','FLAT 1000','BEACH ROAD','BN23 5HT'),
(635532,'Mr X','01903773333','FLAT 1000','BEACH ROAD','BN23 5HT'),
(635532,'Mr X','01903774444' ,'FLAT 1000','BEACH ROAD','BN23 5HT')
使用带有CASE语句和窗口函数的CTE查询将电话号码放在正确的标题下:
;WITH CTE AS (
SELECT #temp.Customer_No,
#temp.Name,
CASE WHEN Row_number()OVER(partition BY Customer_No ORDER BY Telephone_No) = 1 THEN #temp.Telephone_No END AS Telephone_No_1,
CASE WHEN Row_number()OVER(partition BY Customer_No ORDER BY Telephone_No) = 2 THEN #temp.Telephone_No END AS Telephone_No_2,
CASE WHEN Row_number()OVER(partition BY Customer_No ORDER BY Telephone_No) = 3 THEN #temp.Telephone_No END AS Telephone_No_3,
CASE WHEN Row_number()OVER(partition BY Customer_No ORDER BY Telephone_No) = 4 THEN #temp.Telephone_No END AS Telephone_No_4,
#temp.Address,
#temp.Street_Name,
#temp.Postcode
FROM #temp)
SELECT CTE.Customer_No,
CTE.Name,
MAX(CTE.Telephone_No_1) Telephone_No_1,
MAX(CTE.Telephone_No_2) Telephone_No_2,
MAX(CTE.Telephone_No_3) Telephone_No_3,
MAX(CTE.Telephone_No_4) Telephone_No_4,
CTE.Address,
CTE.Street_Name,
CTE.Postcode
FROM CTE
GROUP BY CTE.Customer_No,
CTE.Name,
CTE.Address,
CTE.Street_Name,
CTE.Postcode;
结果:
以下是上述动态版本,因此您无需担心电话号码的数量:
创建样本数据
IF OBJECT_ID('tempdb..#TEMP') IS NOT NULL
DROP TABLE #TEMP;
CREATE TABLE #temp (Customer_No INT, Name VARCHAR(100), Telephone_No VARCHAR(100), Address VARCHAR(100), Street_Name VARCHAR(100), Postcode VARCHAR(100))
INSERT INTO #temp
VALUES
(635532,'Mr X','0771111111','FLAT 1000','BEACH ROAD','BN23 5HT'),
(635532,'Mr X','0771112222','FLAT 1000','BEACH ROAD','BN23 5HT'),
(635532,'Mr X','01903773333','FLAT 1000','BEACH ROAD','BN23 5HT'),
(635532,'Mr X','01903774444' ,'FLAT 1000','BEACH ROAD','BN23 5HT')
解决方案的动态部分,它将生成类似于上述查询的查询:
IF OBJECT_ID('tempdb..#TEMP2') IS NOT NULL
DROP TABLE #TEMP2;
SELECT #temp.Customer_No,
#temp.Name,
Row_number()OVER(partition BY Customer_No ORDER BY Telephone_No) AS rn,
#temp.Telephone_No,
#temp.Address,
#temp.Street_Name,
#temp.Postcode INTO #temp2
FROM #temp
DECLARE @SQL1 VARCHAR(max) ='';
SELECT @SQL1 = '
;WITH CTE AS (
SELECT #TEMP2.Customer_No,
#TEMP2.Name, '
SELECT @SQL1+='CASE WHEN rn ='+CAST(rn AS VARCHAR)+'THEN #TEMP2.Telephone_No END AS Telephone_No_'+CAST(rn AS VARCHAR)+',' FROM #temp2
SELECT @SQL1+= '#TEMP2.Address,
#TEMP2.Street_Name,
#TEMP2.Postcode
FROM #TEMP2)
SELECT CTE.Customer_No,
CTE.Name,'
SELECT @SQL1+='MAX(CTE.Telephone_No_'+CAST(rn AS VARCHAR)+') AS Telephone_No_'+CAST(rn AS VARCHAR)+','FROM #temp2
SELECT @SQL1+='CTE.Address,
CTE.Street_Name,
CTE.Postcode
FROM CTE
GROUP BY CTE.Customer_No,
CTE.Name,
CTE.Address,
CTE.Street_Name,
CTE.Postcode;'
PRINT(@SQL1)
EXECUTE (@SQL1)
打印声明的结果:
整个查询的结果:
答案 1 :(得分:0)
我不认为这是一个直接的支点。这是一个工作示例
CREATE TABLE #test
(
Customer_No INT,
NAME VARCHAR(50),
Telephone_No NUMERIC(15),
Address VARCHAR(50),
Street_Name VARCHAR(50),
Postcode VARCHAR(50)
)
insert #test values
(635532 ,'Mr X' , 0771111111 ,'FLAT 1000' , 'BEACH ROAD' , 'BN23 5HT'),
(635532 ,'Mr X' , 0771112222 ,'FLAT 1000' , 'BEACH ROAD' , 'BN23 5HT'),
(635532 ,'Mr X' , 01903773333 ,'FLAT 1000' , 'BEACH ROAD' , 'BN23 5HT'),
(635532 ,'Mr X' , 01903774444 ,'FLAT 1000' , 'BEACH ROAD' , 'BN23 5HT'),
(635533 ,'Mr X' , 01903774444 ,'FLAT 1000' , 'BEACH ROAD' , 'BN23 5HT')
DECLARE @sql NVARCHAR(max),
@cnt INT,
@incr INT = 1
SELECT @cnt = (SELECT TOP 1 Count(1) AS cnt
FROM #test
GROUP BY Customer_No
ORDER BY cnt DESC) --To get the max phone number count
SET @sql = '
;with cte as
(
SELECT Row_number()OVER(partition BY Customer_No ORDER BY Telephone_No) as t_list,
*
FROM #test
)
select Customer_No,Name,'
WHILE @incr <= @cnt -- used just to frame the query
BEGIN
SET @sql += 'max(case when t_list = '+ Cast(@incr AS VARCHAR(15))+ ' then Telephone_No end) as Telephone_No'
+ Cast(@incr AS VARCHAR(15)) + ','
SET @incr+=1
END
SET @sql+= 'Address ,Street_Name ,Postcode from cte group by Customer_No,Name,Address ,Street_Name ,Postcode'
--PRINT @sql
EXEC Sp_executesql @sql
<强>结果:强>
╔═════════════╦══════╦════════════════╦════════════════╦════════════════╦════════════════╦═══════════╦═════════════╦══════════╗
║ Customer_No ║ Name ║ Telephone_No_1 ║ Telephone_No_2 ║ Telephone_No_3 ║ Telephone_No_4 ║ Address ║ Street_Name ║ Postcode ║
╠═════════════╬══════╬════════════════╬════════════════╬════════════════╬════════════════╬═══════════╬═════════════╬══════════╣
║ 635532 ║ Mr X ║ 771111111 ║ 771112222 ║ 1903773333 ║ 1903774444 ║ FLAT 1000 ║ BEACH ROAD ║ BN23 5HT ║
║ 635533 ║ Mr X ║ 1903774444 ║ NULL ║ NULL ║ NULL ║ FLAT 1000 ║ BEACH ROAD ║ BN23 5HT ║
╚═════════════╩══════╩════════════════╩════════════════╩════════════════╩════════════════╩═══════════╩═════════════╩══════════╝
答案 2 :(得分:0)
首先,我赞赏你纠正这个悲惨的数据库结构。做得好,一旦完成,你将永远感激。
这是经过测试的,可行。可能有更简单的方法(尽可能避免使用动态SQL),但是row_over分区是您正在寻找的。
declare @Table table(
Customer_No varchar(50),
Name varchar(50),
Telephone_No varchar(20),
Address varchar(50),
Street_Name varchar(50),
Postcode varchar(50))
insert into @Table
VALUES
(635532, 'Mr. X', '0771111111', 'Flat', '1000 Beach Road', 'Bn23 5HT'),
(635532, 'Mr. X', '0771112222', 'Flat', '1000 Beach Road', 'Bn23 5HT'),
(635532, 'Mr. X', '01903773333', 'Flat', '1000 Beach Road', 'Bn23 5HT')
declare @RowNumberTable table(
Customer_No varchar(50),
Name varchar(50),
Telephone_No varchar(50),
Address varchar(50),
Street_Name varchar(50),
Postcode varchar(50),
row_number int)
INSERT INTO @RowNumberTable
SELECT Customer_No,
Name,
Telephone_No,
Address,
Street_Name,
Postcode,
row_number() over(partition by Customer_No order by Telephone_No) as rn
FROM @Table
SELECT T1.Customer_No,
T1.Name,
T1.Telephone_No,
T2.Telephone_No as [Telephone 2],
T3.Telephone_No as [Telephone 3],
T4.Telephone_No as [Telephone 4],
T5.Telephone_No as [Telephone 5],
T6.Telephone_No as [Telephone 6],
T7.Telephone_No as [Telephone 7],
T8.Telephone_No as [Telephone 8],
T9.Telephone_No as [Telephone 9],
T10.Telephone_No as [Telephone 10],
T1.Address,
T1.Street_Name,
T1.Postcode
FROM @RowNumberTable T1
LEFT OUTER JOIN @RowNumberTable T2 ON T1.Customer_No = T2.Customer_No AND T2.row_number = 2
LEFT OUTER JOIN @RowNumberTable T3 ON T1.Customer_No = T3.Customer_No AND T3.row_number = 3
LEFT OUTER JOIN @RowNumberTable T4 ON T1.Customer_No = T4.Customer_No AND T4.row_number = 4
LEFT OUTER JOIN @RowNumberTable T5 ON T1.Customer_No = T5.Customer_No AND T5.row_number = 5
LEFT OUTER JOIN @RowNumberTable T6 ON T1.Customer_No = T6.Customer_No AND T6.row_number = 6
LEFT OUTER JOIN @RowNumberTable T7 ON T1.Customer_No = T7.Customer_No AND T7.row_number = 7
LEFT OUTER JOIN @RowNumberTable T8 ON T1.Customer_No = T8.Customer_No AND T8.row_number = 8
LEFT OUTER JOIN @RowNumberTable T9 ON T1.Customer_No = T9.Customer_No AND T9.row_number = 9
LEFT OUTER JOIN @RowNumberTable T10 ON T1.Customer_No = T10.Customer_No AND T10.row_number = 10
WHERE T1.row_number = 1
结果:
Customer_No Name Telephone_No Telephone 2 Telephone 3 Telephone 4 Telephone 5 Telephone 6 Telephone 7 Telephone 8 Telephone 9 Telephone 10 Address Street_Name Postcode
-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- --------------------------------------------------
635532 Mr. X 01903773333 0771111111 0771112222 NULL NULL NULL NULL NULL NULL NULL Flat 1000 Beach Road Bn23 5HT
答案 3 :(得分:0)
假设表格模式看起来像这样(你需要一种方法来唯一地标识每一行):
create table dbo.customer
(
customer_no int not null ,
telephone_no varchar(32) not null ,
name varchar(32) not null ,
address varchar(32) not null ,
street_name varchar(32) not null ,
postcode varchar(32) not null ,
primary key clustered ( customer_no , telephone_no ) ,
)
这样的事情可以让你得到你想要的桌子旋转:
with t1 as (
select customer_no = c.customer_no ,
telephone_no = min( c.telephone_no )
from dbo.customer c
group by c.customer_no
) ,
c as (
select c.*
from dbo.customer c
join t1 on t1.customer_no = c.customer_no
and t1.telephone_no = c.telephone_no
) ,
t2 as (
select customer_no = c.customer_no ,
telephone_no = min( c.telephone_no )
from dbo.customer c
join t1 t on t.customer_no = c.customer_no
and t.telephone_no < c.telephone_no
group by c.customer_no
),
t3 as (
select customer_no = c.customer_no ,
telephone_no = min( c.telephone_no )
from dbo.customer c
join t2 t on t.customer_no = c.customer_no
and t.telephone_no < c.telephone_no
group by c.customer_no
),
t4 as (
select customer_no = c.customer_no ,
telephone_no = min( c.telephone_no )
from dbo.customer c
join t3 t on t.customer_no = c.customer_no
and t.telephone_no < c.telephone_no
group by c.customer_no
),
t5 as (
select customer_no = c.customer_no ,
telephone_no = min( c.telephone_no )
from dbo.customer c
join t4 t on t.customer_no = c.customer_no
and t.telephone_no < c.telephone_no
group by c.customer_no
),
t6 as (
select customer_no = c.customer_no ,
telephone_no = min( c.telephone_no )
from dbo.customer c
join t5 t on t.customer_no = c.customer_no
and t.telephone_no < c.telephone_no
group by c.customer_no
),
t7 as (
select customer_no = c.customer_no ,
telephone_no = min( c.telephone_no )
from dbo.customer c
join t6 t on t.customer_no = c.customer_no
and t.telephone_no < c.telephone_no
group by c.customer_no
),
t8 as (
select customer_no = c.customer_no ,
telephone_no = min( c.telephone_no )
from dbo.customer c
join t7 t on t.customer_no = c.customer_no
and t.telephone_no < c.telephone_no
group by c.customer_no
),
t9 as (
select customer_no = c.customer_no ,
telephone_no = min( c.telephone_no )
from dbo.customer c
join t8 t on t.customer_no = c.customer_no
and t.telephone_no < c.telephone_no
group by c.customer_no
),
t10 as (
select customer_no = c.customer_no ,
telephone_no = min( c.telephone_no )
from dbo.customer c
join t9 t on t.customer_no = c.customer_no
and t.telephone_no < c.telephone_no
group by c.customer_no
)
select customer_no = c.customer_no ,
name = c.name ,
addr = c.address ,
street = c.street_name ,
postcode = c.postcode ,
tel_1 = t1.telephone_no ,
tel_2 = t2.telephone_no ,
tel_3 = t2.telephone_no ,
tel_4 = t2.telephone_no ,
tel_5 = t2.telephone_no ,
tel_6 = t2.telephone_no ,
tel_7 = t2.telephone_no ,
tel_8 = t2.telephone_no ,
tel_9 = t2.telephone_no ,
tel_10 = t2.telephone_no
from c
left join t1 on t1.customer_no = c.customer_no and t1.telephone_no = c.telephone_no
left join t2 on t2.customer_no = c.customer_no and t2.telephone_no = c.telephone_no
left join t3 on t3.customer_no = c.customer_no and t3.telephone_no = c.telephone_no
left join t4 on t4.customer_no = c.customer_no and t4.telephone_no = c.telephone_no
left join t5 on t5.customer_no = c.customer_no and t5.telephone_no = c.telephone_no
left join t6 on t6.customer_no = c.customer_no and t6.telephone_no = c.telephone_no
left join t7 on t7.customer_no = c.customer_no and t7.telephone_no = c.telephone_no
left join t8 on t8.customer_no = c.customer_no and t8.telephone_no = c.telephone_no
left join t9 on t9.customer_no = c.customer_no and t9.telephone_no = c.telephone_no
left join t10 on t10.customer_no = c.customer_no and t10.telephone_no = c.telephone_no
;