変更履歴を製品に保存し、Col1またはCol2またはCol3に変更を加えたレコードのリストを取得したいが、これらの3つの列のいずれかが変更されます。Linq履歴のフィルタ行の差異
ここではSQLで行われた例を示します。 Linqとどうやってやりますか?
CREATE TABLE #ProductHistorical(
IdProductHistorical int IDENTITY(1,1) NOT NULL,
IdProduct int NOT NULL,
DateChange datetime NULL,
Col1 int NOT NULL,
Col2 int NOT NULL,
Col3 int NOT NULL,
CONSTRAINT PK_ProductHistorical PRIMARY KEY CLUSTERED (IdProductHistorical ASC))
GO
挿入試験データ
INSERT #ProductHistorical (IdProduct, DateChange, Col1, Col2, Col3) VALUES (1, CAST(0x0000A13900000000 AS DateTime), 1, 2, 3)
INSERT #ProductHistorical (IdProduct, DateChange, Col1, Col2, Col3) VALUES (1, CAST(0x0000A13A00000000 AS DateTime), 1, 2, 3)
INSERT #ProductHistorical (IdProduct, DateChange, Col1, Col2, Col3) VALUES (1, CAST(0x0000A13B00000000 AS DateTime), 1, 2, 3)
INSERT #ProductHistorical (IdProduct, DateChange, Col1, Col2, Col3) VALUES (1, CAST(0x0000A13C00000000 AS DateTime), 1, 1, 3)
INSERT #ProductHistorical (IdProduct, DateChange, Col1, Col2, Col3) VALUES (1, CAST(0x0000A13D00000000 AS DateTime), 1, 1, 3)
INSERT #ProductHistorical (IdProduct, DateChange, Col1, Col2, Col3) VALUES (1, CAST(0x0000A13E00000000 AS DateTime), 2, 2, 2)
INSERT #ProductHistorical (IdProduct, DateChange, Col1, Col2, Col3) VALUES (1, CAST(0x0000A13F00000000 AS DateTime), 2, 2, 2)
INSERT #ProductHistorical (IdProduct, DateChange, Col1, Col2, Col3) VALUES (1, CAST(0x0000A14000000000 AS DateTime), 2, 2, 2)
INSERT #ProductHistorical (IdProduct, DateChange, Col1, Col2, Col3) VALUES (1, CAST(0x0000A14100000000 AS DateTime), 1, 2, 3)
INSERT #ProductHistorical (IdProduct, DateChange, Col1, Col2, Col3) VALUES (2, CAST(0x0000A14200000000 AS DateTime), 1, 1, 1)
INSERT #ProductHistorical (IdProduct, DateChange, Col1, Col2, Col3) VALUES (2, CAST(0x0000A14300000000 AS DateTime), 1, 1, 2)
SQLクエリ
SELECT phWithChanges.DateChange,
phWithChanges.Col1,
phWithChanges.Col2,
phWithChanges.Col3
FROM #ProductHistorical ph
CROSS APPLY (
SELECT TOP 1 *
FROM #ProductHistorical phPost
WHERE phPost.IdProduct=ph.IdProduct AND
phPost.IdProductHistorical>ph.IdProductHistorical AND
(phPost.Col1<>ph.Col1 OR phPost.Col2<>ph.Col2 OR phPost.Col2<>ph.Col2)
ORDER BY phPost.IdProductHistorical ASC) phWithChanges
WHERE ph.IdProduct=1
GROUP BY phWithChanges.DateChange,phWithChanges.Col1,phWithChanges.Col2,phWithChanges.Col3
UNION
--Add First Row
SELECT * FROM
(SELECT TOP 1
phFirst.DateChange,
phFirst.Col1,
phFirst.Col2,
phFirst.Col3
FROM #ProductHistorical phFirst
WHERE phFirst.IdProduct=1 ORDER BY phFirst.IdProductHistorical) rowFirst
ORDER BY 1
データ
IdProductHistorical IdProduct DateChange Col1 Col2 Col3
------------------- ----------- ----------------------- ----------- ----------- -----------
1 1 2013-01-01 00:00:00.000 1 2 3
2 1 2013-01-02 00:00:00.000 1 2 3
3 1 2013-01-03 00:00:00.000 1 2 3
4 1 2013-01-04 00:00:00.000 1 1 3
5 1 2013-01-05 00:00:00.000 1 1 3
6 1 2013-01-06 00:00:00.000 2 2 2
7 1 2013-01-07 00:00:00.000 2 2 2
8 1 2013-01-08 00:00:00.000 2 2 2
9 1 2013-01-09 00:00:00.000 1 2 3
10 2 2013-01-10 00:00:00.000 1 1 1
11 2 2013-01-11 00:00:00.000 1 1 2
をテストするための一時テーブルを作成します。あなたがLINQので行うにはどうすればよい
結果
DateChange Col1 Col2 Col3
----------------------- ----------- ----------- -----------
2013-01-01 00:00:00.000 1 2 3
2013-01-04 00:00:00.000 1 1 3
2013-01-06 00:00:00.000 2 2 2
2013-01-09 00:00:00.000 1 2 3
?
まずアプローチ
var query=(
from ph in ProductHistorical.Where(p=>p.IdProduct==1)
orderby ph.DateChange ascending
select new ProductHistoricalItem
{
DateChange = ph.DataChange,
Col1 = ph.Col1,
Col2 = ph.Col2,
Col3 = ph.Col3
});
List<ProductHistoricalItem> listResult=new List<ProductHistoricalItem>();
ProductHistoricalItem previous = null;
foreach (ProductHistoricalItem item in query)
{
if (previous == null ||
previous.Col1 != item.Col1 ||
previous.Col2 != item.Col2 ||
previous.Col3 != item.Col3)
{
listResult.Add(item);
previous = item;
}
}
これは非常に効率的ではありません。どのように私はループを使用せずにそれを行うことができますか?
+1 create tableとinserts文を与えるためです。 –