很抱歉,如果之前已经问过这个问题,但我无法找到我想要的地方。
设置:我有一个包含3个表的MS SQL数据库
表 - FoodInfo 列 - FoodId(PK),DanName
表 - CompName 列 - CmpId(PK),CmpName
表 - 营养素(连接表) 列 - FoodId(FK),CmpId(fk),BestLoc
对于每个DanName行,大约有8个CmpName,每个CmpName都有一个关联的1个BestLoc
当我在winform中显示数据时,这会导致DanName重复8次。
问题是,我想在一行中显示DanName以及相关的CmpName及其值。
像: DanName - CmpName1 - BestLoc值 - CmpName2 - BestLoc值 - CmpName3 - BestLoc值..等等。
我对解决方案非常灵活,但我不确定要遵循的路径。 我应该尝试在DB中创建一个看起来像我想要的表并将其放在DataGridView中,或者我应该尝试使用Linq-To-SQL解决它并将其放在listview中?
如上所述,我对解决方案非常灵活,我只是不想在文本框中输入数据。 我也希望能够使用我检索的数据并在程序的其他地方使用它。
如果有人有解决方案,我很乐意看到它的一个例子。
修改 更详细一些,以及一些代码示例。
我的带有linq的DAL课程
void bw_DoWork(object sender, DoWorkEventArgs e)
{
Table<FoodInfo> FoodInfo = db.GetTable<FoodInfo>();
Table<CompName> CompName = db.GetTable<CompName>();
Table<Nutrient> Nutrients = db.GetTable<Nutrient>();
var foods =
from compname in CompName
join nutrients in Nutrients on compname.CompId equals nutrients.CompId
join foodinfo in FoodInfo on nutrients.FoodId equals foodinfo.FoodId
where foodinfo.DanName.StartsWith(searchWord) && (compname.CompId >= 0
&& compname.CompId < 8)
select new { foodinfo.DanName, compname.CmpNamDK, nutrients.BestLoc };
foreach (var food in foods)
{
DanName = food.DanName;
Compname = food.CmpNamDK;
BestLoc = food.BestLoc;
OnSearchResultArgs OSR = new OnSearchResultArgs(DanName, Compname, BestLoc);
onResult(this, OSR);
}
}
在我的表单中触发一个eventhandler并发送结果并执行此代码:
listView1.FullRowSelect = true;
listView1.Columns.Add("DanName", 100);
listView1.Columns.Add("CompName", 150);
listView1.Columns.Add("BestLoc", 50);
private void UpdateControls(object sender, OnSearchResultArgs e)
{
var item = new ListViewItem();
item.Text = e.DanName;
item.SubItems.Add(e.CompName);
item.SubItems.Add(e.BestLoc);
listView1.Items.Add(item);
}
UpdateControl正在被调用,但我不认为有必要放在这里。
通过这个,我得到以下内容:
我想把这8行变成1行。像:
答案 0 :(得分:0)
我有两个解决方案,都有它们的缺点。
第一个解决方案是手动转移数据,但这不是非常动态的,因为如果你开始拥有超过8个CmpName你将不得不改变查询,第二个解决方案是将所有CmpName和BestLoc值放入一栏。
下面的T-SQL应该演示两种解决方案。
--** Set up test data
DECLARE @FoodInfo Table (FoodId INT, DanName varchar(50));
DECLARE @CompName TABLE (CmpId INT, CmpName VARCHAR(50));
DECLARE @Nutrients TABLE (FoodId INT , CmpId INT, BestLoc VARCHAR(50));
INSERT INTO @FoodInfo (FoodId, DanName)
VALUES (1, 'Abrikos, torret');
INSERT INTO @CompName (CmpId, CmpName)
VALUES (1, 'Energi'),(2, 'Protein, total'),(3, 'total-N'),(4, 'Fedt, total'),(5, 'Maettede fedtsyrer'),(6, 'monoumaett, fedtsyrer'),(7, 'polyumaett, fedtsyrer'),(8, 'kulhydrat, tilgaengelig');
INSERT INTO @Nutrients(FoodId, CmpId, BestLoc)
VALUES (1,1,1159),(1,2,2.9),(1,3,0.5),(1,4,1.7),(1,5,0.1),(1,6,0.6),(1,7,0.6),(1,8,57.2);
--** Standard query
SELECT fi.DanName
, cn.CmpName
, n.BestLoc
FROM @FoodInfo AS fi
JOIN @Nutrients AS n
ON fi.FoodId = n.FoodId
JOIN @CompName AS cn
ON n.CmpId = cn.CmpId;
--** Manual Pivot
WITH sortCTE AS (
SELECT fi.DanName
, cn.CmpName
, n.BestLoc
, ROW_NUMBER() OVER (PARTITION BY fi.FoodId ORDER BY cn.CmpId) AS 'col'
FROM @FoodInfo AS fi
JOIN @Nutrients AS n
ON fi.FoodId = n.FoodId
JOIN @CompName AS cn
ON n.CmpId = cn.CmpId)
SELECT s.DanName
, MAX(CASE WHEN s.col = 1 THEN s.CmpName END) AS Cmp1
, MAX(CASE WHEN s.col = 1 THEN s.BestLoc END) AS BestLoc1
, MAX(CASE WHEN s.col = 2 THEN s.CmpName END) AS Cmp2
, MAX(CASE WHEN s.col = 2 THEN s.BestLoc END) AS BestLoc2
, MAX(CASE WHEN s.col = 3 THEN s.CmpName END) AS Cmp3
, MAX(CASE WHEN s.col = 3 THEN s.BestLoc END) AS BestLoc3
, MAX(CASE WHEN s.col = 4 THEN s.CmpName END) AS Cmp4
, MAX(CASE WHEN s.col = 4 THEN s.BestLoc END) AS BestLoc4
, MAX(CASE WHEN s.col = 5 THEN s.CmpName END) AS Cmp5
, MAX(CASE WHEN s.col = 5 THEN s.BestLoc END) AS BestLoc5
, MAX(CASE WHEN s.col = 6 THEN s.CmpName END) AS Cmp6
, MAX(CASE WHEN s.col = 6 THEN s.BestLoc END) AS BestLoc6
, MAX(CASE WHEN s.col = 7 THEN s.CmpName END) AS Cmp7
, MAX(CASE WHEN s.col = 7 THEN s.BestLoc END) AS BestLoc7
, MAX(CASE WHEN s.col = 8 THEN s.CmpName END) AS Cmp8
, MAX(CASE WHEN s.col = 8 THEN s.BestLoc END) AS BestLoc8
FROM sortCTE AS s
GROUP BY s.DanName;
--** All in one column
SELECT fi.DanName
, ISNULL(SUBSTRING((SELECT ', ' + cn.CmpName + ' - ' + CONVERT(VARCHAR(8), n.BestLoc)
FROM @Nutrients AS n
JOIN @CompName AS cn
ON n.CmpId = cn.CmpId
WHERE fi.FoodId = n.FoodId
ORDER BY cn.CmpId ASC FOR XML PATH('') ), 3, 5000), '') AS 'Cmp'
FROM @FoodInfo AS fi;
我很抱歉,但我不知道LINQ中的等效查询会是什么样子,但是这可以让你知道你的目标是什么。
我希望这会有所帮助。
答案 1 :(得分:0)
如果有人遇到与我相同的问题,只需更新。
首先我尝试了@JonPayne的解决方案,使用了T-SQL ..它解决了我的问题,但对我来说工作得很慢。 Maby我做错了。我不知道。
我最终使用我在此处找到的指南制作了一个数据透视方法:http://www.codeproject.com/Articles/22008/C-Pivot-Table
非常简单,我从SQL-Server查询无序数据,将其放入数据表并使用pivot方法格式化数据表,返回有序的数据表。