Frage

Ich habe den Nachmittag damit verbracht, meinen Geist herum zu wickeln, wie die folgende Abfrage in LINQ zu übersetzen, aber ich kann ganz da nicht bekommen.

declare @productId int; set @productId = 3212;

select * from InformationData data where productId = @productId and orgId = 1
and exists(
    select id from (
        select coalesce(id1.id, id2.id, id3.id) as id from (
            select productId,attributeId from InformationData where productId = @productId group by productId,attributeId
        ) id
        left outer join InformationData id1 on id1.productId = id.productId and id1.attributeId = id.attributeId and id1.language = 1
        left outer join InformationData id2 on id2.productId = id.productId and id2.attributeId = id.attributeId and id2.language = 2
        left outer join InformationData id3 on id3.productId = id.productId and id3.attributeId = id.attributeId and id3.language = 0
    ) row
    where row.id = data.id
)

Der Zweck der Abfrage von Daten aus einer Tabelle mit zwei Ausweich Sprachen zu holen, so dass, wenn die Daten nicht in der Sprache existieren 1 ist es geholt in Sprache 2, und wenn 2 nicht existiert ist es hergeholt für Sprache 0 das eine globale Übersetzung.

Ich kann die innere Abfrage meist korrekt erhalten (mit Ausnahme von id1.language = 1, kann ich nicht scheinen, um es auf einem Mitglied der Tabelle Ich bin Beitritt zu verbinden, irgendwelche Ideen?)

Dies ist mein Code (LINQPad Code):

(
    from data in (
        from d in InformationData where d.ProductId == 3212 group d by new { d.ProductId, d.AttributeId } into p select new { ProductId = p.Key.ProductId, AttributeId = p.Key.AttributeId }
    )
    join x1 in InformationData on new { a = data.ProductId, b = data.AttributeId } equals new { a = x1.ProductId, b = x1.AttributeId } into f1
        from r1 in f1.DefaultIfEmpty()
        where r1.Language == 1
    join x2 in InformationData on new { a = data.ProductId, b = data.AttributeId } equals new { a = x2.ProductId, b = x2.AttributeId } into f2
        from r2 in f2.DefaultIfEmpty()
        where r2.Language == 2
    join x3 in InformationData on new { a = data.ProductId, b = data.AttributeId } equals new { a = x3.ProductId, b = x3.AttributeId } into f3
        from r3 in f3.DefaultIfEmpty()
        where r3.Language == 2
    select new { Id = ((int?)r1.Id) ?? ((int?)r2.Id) ?? r3.Id }
).Dump();

Welche generiert die folgende SQL:

-- Region Parameters
DECLARE @p0 Int SET @p0 = 3212
DECLARE @p1 Int SET @p1 = 2
DECLARE @p2 Int SET @p2 = 2
DECLARE @p3 Int SET @p3 = 1
-- EndRegion
SELECT COALESCE([t2].[id],COALESCE([t3].[id],[t4].[id])) AS [Id]
FROM (
    SELECT [t0].[productId], [t0].[attributeId]
    FROM [InformationData] AS [t0]
    WHERE [t0].[productId] = @p0
    GROUP BY [t0].[productId], [t0].[attributeId]
    ) AS [t1]
LEFT OUTER JOIN [InformationData] AS [t2] ON ([t1].[productId] = [t2].[productId]) AND ([t1].[attributeId] = [t2].[attributeId])
LEFT OUTER JOIN [InformationData] AS [t3] ON ([t1].[productId] = [t3].[productId]) AND ([t1].[attributeId] = [t3].[attributeId])
LEFT OUTER JOIN [InformationData] AS [t4] ON ([t1].[productId] = [t4].[productId]) AND ([t1].[attributeId] = [t4].[attributeId])
WHERE ([t4].[language] = @p1) AND ([t3].[language] = @p2) AND ([t2].[language] = @p3)

Aber ich kann das nicht mit dem Rest der Abfrage zusammen, vielleicht bin ich nur müde kaufen Ich erhalte es eine Menge von CROSS APPLY ist zu tun. Hat jemand irgendwelche Vorschläge?

War es hilfreich?

Lösung

Nun nach einem guten Schlaf und einige Knirschen Dinge wurde ein wenig heller und fand ich die Lösung :) Für alle, die es merkwürdig, hier ist


(
    from i in InformationData
    where (
        from data in (
            from d in InformationData where d.ProductId == 3212 group d by new { d.ProductId, d.AttributeId } into p select new { ProductId = p.Key.ProductId, AttributeId = p.Key.AttributeId }
        )
        join x1 in InformationData on new { a = data.ProductId, b = data.AttributeId, c = 1} equals new { a = x1.ProductId, b = x1.AttributeId, c = x1.Language } into f1
            from r1 in f1.DefaultIfEmpty()
        join x2 in InformationData on new { a = data.ProductId, b = data.AttributeId, c = 2 } equals new { a = x2.ProductId, b = x2.AttributeId, c = x2.Language } into f2
            from r2 in f2.DefaultIfEmpty()
        join x3 in InformationData on new { a = data.ProductId, b = data.AttributeId, c = 0 } equals new { a = x3.ProductId, b = x3.AttributeId, c = x3.Language } into f3
            from r3 in f3.DefaultIfEmpty()
        select new { Id = ((int?)r1.Id) ?? ((int?)r2.Id) ?? r3.Id }
    ).Any(d => d.Id == i.Id)
    select i
).Dump();

Und hier ist die erzeugte SQL


-- Region Parameters
DECLARE @p0 Int SET @p0 = 3212
DECLARE @p1 Int SET @p1 = 1
DECLARE @p2 Int SET @p2 = 2
DECLARE @p3 Int SET @p3 = 0
-- EndRegion
SELECT [t0].[id] AS [Id], [t0].[attributeId] AS [AttributeId], [t0].[productId] AS [ProductId], [t0].[value] AS [Value], [t0].[orgId] AS [OrgId], [t0].[version] AS [Version], [t0].[language] AS [Language], [t0].[metaType] AS [MetaType], [t0].[overload] AS [Overload], [t0].[parentId] AS [ParentId]
FROM [InformationData] AS [t0]
WHERE EXISTS(
    SELECT NULL AS [EMPTY]
    FROM (
        SELECT COALESCE([t3].[id],COALESCE([t4].[id],[t5].[id])) AS [value]
        FROM (
            SELECT [t1].[productId], [t1].[attributeId]
            FROM [InformationData] AS [t1]
            WHERE [t1].[productId] = @p0
            GROUP BY [t1].[productId], [t1].[attributeId]
            ) AS [t2]
        LEFT OUTER JOIN [InformationData] AS [t3] ON ([t2].[productId] = [t3].[productId]) AND ([t2].[attributeId] = [t3].[attributeId]) AND (@p1 = [t3].[language])
        LEFT OUTER JOIN [InformationData] AS [t4] ON ([t2].[productId] = [t4].[productId]) AND ([t2].[attributeId] = [t4].[attributeId]) AND (@p2 = [t4].[language])
        LEFT OUTER JOIN [InformationData] AS [t5] ON ([t2].[productId] = [t5].[productId]) AND ([t2].[attributeId] = [t5].[attributeId]) AND (@p3 = [t5].[language])
        ) AS [t6]
    WHERE [t6].[value] = [t0].[id]
    )

Andere Tipps

Auf der Basis meist auf Ihrer Beschreibung dessen, was die Abfrage tun soll, ich glaube, Sie in der Lage sein kann, um das gleiche Ergebnis mit dem entsprechenden „orderby“ -Klausel und Abrufen nur das erste Ergebnis zu erreichen. Wie folgt aus:

var result =
(
    from d in InformationData
    where d.ProductId == 3212
    orderby ((d.language == 0) ? Int32.MaxValue : d.language)
    select d
).First();

Bearbeiten : Sie können die Suche Vorrang steuern, indem die orderby Klausel erstreckt. Wenn beispielsweise der Vorrang 2 sein soll, dann 3, dann 1, dann etwas anderes, man könnte dies tun:

var result =
(
    from d in InformationData
    where d.ProductId == 3212
    orderby
        (d.language == 2) ? 0
        : (d.language == 3) ? 1
        : (d.language == 1) ? 2
        : Int32.MaxValue
    select d
).First();
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top