如果这是一个DBA问题,请随时告诉我。
我们有数据存储在需要导出的SQL数据库中,因此可以将其转换为新的软件包。目前,我们有一个父记录集和一个需要组合的子记录集,因为新系统能够跟踪父记录集中的子记录集。我希望这是有道理的。
父记录集
ID | Description
-- | -----------
1 | Item 1
2 | Item 2
3 | Item 3
儿童记录集
Parent ID | Code | Value (string)
--------- | ----------- | -------------------
1 | PSI | 75
1 | SIZE | 2 1/2"
2 | CFM | 9200
2 | BELT | BROWING - A76
2 | RPM | 722
3 | PSI | 45
3 | SIZE | 1"
理想情况下,我们需要一个以某种方式显示的CSV文件:
ID | Description | PSI | SIZE | CFM | BELT | RPM
-- | -----------
1 | Item 1
2 | Item 2
3 | Item 3
你得到了照片。
我不在乎它是否在SQL,Excel,Access或某些魔法(试图避免编写程序)中完成,我试图节省工作人员需要的时间手动更改订单或输入订单。有关如何轻松更改的任何想法?我们正在谈论5700个儿童记录和5900个父记录。是否有一些SQL魔术可以做到这一点?
我确实考虑过单独添加每个列(例如(select value from child where id = parent id and code = 'RPM') as RPM
)但是有157个不同的代码,这也不是理想的。
答案 0 :(得分:1)
假设您想要去DYNAMIC(未经测试)
Declare @SQL varchar(max) = Stuff((Select Distinct ',' + QuoteName(Code) From Child Order by 1 For XML Path('')),1,1,'')
Select @SQL = '
Select [ID],[Description],' + @SQL + '
From (
Select A.ID
,A.Description
,B.Code
,B.Value
From Parent A
Join Child B on (A.ID=B.ParentID)
) A
Pivot (max(Value) For [Code] in (' + @SQL + ') ) p'
Exec(@SQL);
修改强>
如果列需要按特定顺序
Select A.ID
,A.Description
,PSI = max(case when B.Code='PSI' then B.Value end)
,Size = max(case when B.Code='Size' then B.Value end)
,CFM = max(case when B.Code='CFM' then B.Value end)
-- ... more fields
From Parent A
Join Child B on (A.ID=B.ParentID)
Group By A.ID,A.Description
答案 1 :(得分:0)
我认为您可以使用以下内容在SQL中将其删除...
SELECT
parent_id AS `ID`,
MAX(CASE WHEN `code` = 'PSI' THEN `value` ELSE NULL END) AS `PSI`,
MAX(CASE WHEN `code` = 'SIZE' THEN `value` ELSE NULL END) AS `SIZE`,
MAX(CASE WHEN `code` = 'CFM' THEN `value` ELSE NULL END) AS `CFM`,
MAX(CASE WHEN `code` = 'BELT' THEN `value` ELSE NULL END) AS `BELT`,
MAX(CASE WHEN `code` = 'RPM' THEN `value` ELSE NULL END) AS `RPM`
FROM
`child`
GROUP BY
`parent_id`
尝试为模式后面的每个字段创建一个CASE MAX是一个聚合函数,用于避免额外的分组级别。
您可以通过首先使用...
获取代码列表来处理大量代码SELECT DISTINCT `code` from `child`
然后将结果复制到Excel并使用CONCATENATE函数构建MAX(CASE ... lines ...这里的示例...... Excel SQL Building Example
您还可以使用能够处理块编辑的文本编辑器(例如Notepad ++)手动批量构建线条,方法是在块编辑模式下同时键入线条的重复部分(ALT + Click& Drag)。您也可以使用一些聪明的查找和替换操作来为您构建行。
最后,您可以使用自己喜欢的语言编写一个小循环并使用Distinct代码列表来构建SQL,我使用JavaScript构建了一个示例,这里有一个fiddle ,它应该可以直接从小提琴中使用。
答案 2 :(得分:0)
我比当前的数据结构要好得多,但是如果你必须这样做,你可以使用VBA遍历所有字段并创建一个SQL字符串:
Function ConvertTable()
Set db = CurrentDb()
SQL = "Select ParentID"
Set RS = db.OpenRecordset("select Code from ChildRS group by Code")
RS.MoveFirst
Do While Not RS.EOF
code = RS.Fields("Code").Value
SQL = SQL & ", FIRST(iif(code='" & code & "',value)) as [" & code & "]"
RS.MoveNext
Loop
SQL = SQL & " Into [ConvertedTable] From ChildRS group by ParentID"
db.Execute SQL
MsgBox ("done")
End Function
这适用于您指定的少数代码 - 我不知道在所有字段上运行它时是否会超出最大SQL字符串长度的限制。如果是这样,您可能需要弄清楚如何分割数据并将其分成几部分。
答案 3 :(得分:0)
这就是我最终做的事情,@ JohnCappelletti和其他人在此列表中的合并。
首先,我创建了所有可能代码的列表
select (REPLACE(REPLACE(REPLACE(c.Code, ' ', '_'), '.',''),'/','_') + ' =
max(case when d.Code = ''' + c.Code + ''' then d.Value else '''' end),') as text
from code_definitiions c
order by Code
该查询的输出是
AGMA = max(case when d.Code = 'AGMA' then d.Value1 else '' end),
AMB = max(case when d.Code = 'AMB' then d.Value1 else '' end),
AMB_T = max(case when d.Code = 'AMB T' then d.Value1 else '' end),
...
然后我只是将结果复制并粘贴到父查询中。
select m.ID, m.Description,
AGMA = max(case when d.Code = 'AGMA' then d.Value else '' end),
AMB = max(case when d.Code = 'AMB' then d.Value else '' end),
AMB_T = max(case when d.Code = 'AMB T' then d.Value else '' end),
... (the rest of the codes)
from parent m left outer join child d
on m.primary_key = d.foreign_key
group by m.ID, m.Description
order by m.ID
至少达到了我的意图。用户仍然需要进行清理,但它比手动输入要好。