Konvertieren von Outer Apply mit korrelierter Unterabfrage in SQL Server in SQLite

7

Ich muss eine Abfrage in SQL Server in SQlite konvertieren und habe die äußere Anwendung auf die linke äußere Verknüpfung ersetzt. Wie kann ich jedoch die Unterabfrage so einschränken, dass in dieser Situation nur 1 zurückgegeben wird? Und wie übergibt man den Referenzwert aus der äußeren Tabelle an die Unterabfrage?

Ich habe die Dinge hervorgehoben, die ich nicht in Sqlite konvertieren kann. Kann jemand bitte einen Rat geben?

SQL Server:

SELECT  a.id,
        a.CodeValue ,
        a.TotalAmount ,
        InvoiceRevised.RevisedInvoiceId,
        InvoiceRevised.BillNumber AS RevisedInvoice,
        patientlookup.RegistrationNumber AS RegistrationNumber,
        patientlookup.PatientName AS PatientName,
FROM dbo.Invoices a
OUTER APPLY (
SELECT TOP 1 dbo.Invoices.Id AS RevisedInvoiceId,CodeValue AS InvoiceNumber,
    dbo.SCSInvoiceRels.CreatedOn AS InvoiceTime,
    dbo.Invoices.CreatedBy AS InvoiceCreatedBy,
    dbo.Invoices.TotalAmount,dbo.Invoices.Discount,
    dbo.Invoices.RoundAmount 
    FROM Invoices 
    INNER JOIN dbo.SCSInvoiceRels ON dbo.Invoices.Id = dbo.SCSInvoiceRels.InvoiceId 
        AND dbo.SCSInvoiceRels.RecordStatus = 1 AND dbo.Invoices.RecordStatus = 1 AND  dbo.SCSInvoiceRels.SCDetailId IN (
            SELECT SCDetailId FROM dbo.SCSInvoiceRels WHERE InvoiceId = a.id)
) InvoiceRevised
OUTER APPLY (
SELECT TOP 1 pr.CodeValue AS RegistrationNumber,pa.Name AS PatientName FROM dbo.PatientRegs pr 
INNER JOIN dbo.Patients pa ON pa.id = pr.PatientId
INNER JOIN dbo.SCDetails SC ON pr.id = SC.RegId 
INNER JOIN dbo.SCSInvoiceRels SCb ON SC.id = SCb.SCDetailId
WHERE SCb.InvoiceId = a.Id
) patientlookup
WHERE RecordStatus = 0 AND  UpdateOn IS NOT NULL

SQLite:

SELECT  a.id,
        a.CodeValue ,
        a.TotalAmount ,
        InvoiceRevised.RevisedInvoiceId,
        InvoiceRevised.BillNumber AS RevisedInvoice,
        patientlookup.RegistrationNumber AS RegistrationNumber,
        patientlookup.PatientName AS PatientName,
FROM dbo.Invoices a
Left outer join (
SELECT dbo.Invoices.Id AS RevisedInvoiceId,CodeValue AS InvoiceNumber,
    dbo.SCSInvoiceRels.CreatedOn AS InvoiceTime,
    dbo.Invoices.CreatedBy AS InvoiceCreatedBy, 
    dbo.Invoices.TotalAmount,dbo.Invoices.Discount,
    dbo.Invoices.RoundAmount 
    FROM Invoices 
    INNER JOIN dbo.SCSInvoiceRels ON dbo.Invoices.Id = dbo.SCSInvoiceRels.InvoiceId 
        AND dbo.SCSInvoiceRels.RecordStatus = 1 AND dbo.Invoices.RecordStatus = 1 AND  dbo.SCSInvoiceRels.SCDetailId IN (
            SELECT SCDetailId FROM dbo.SCSInvoiceRels WHERE InvoiceId = a.id)
) InvoiceRevised
Left outer join(
SELECT pr.CodeValue AS RegistrationNumber,
       pa.Name AS PatientName,
       SCb.InvoiceId as InvoiceId 
FROM dbo.PatientRegs pr 
INNER JOIN dbo.Patients pa ON pa.id = pr.PatientId
INNER JOIN dbo.SCDetails SC ON pr.id = SC.RegId 
INNER JOIN dbo.SCSInvoiceRels SCb ON SC.id = SCb.SCDetailId
) patientlookup on patientlookup.InvoiceId = a.Id
WHERE RecordStatus = 0 AND  UpdateOn IS NOT NULL
user65898
quelle

Antworten:

10

SQLite unterstützt keine lateralen oder korrelierten Verknüpfungen. Sie können dies mithilfe einer Verknüpfungsbedingung umgehen. Zum Beispiel:

create table t1 (id int, name text);
create table t2 (id int, t1id int references t1(id), name text);
insert into t1 values (1, 'a'), (2, 'b'), (3, 'c');
insert into t2 values (1, 1, 'a1'), (2, 1, 'a2'), (3, 2, 'b1');

Jetzt möchten wir höchstens eine Zeile nach t2sortiert nachschlagen name. Hier ist ein Ansatz, der in SQLite funktioniert:

select  *
from    t1
left join
        t2
on      t2.id =
        (
        select  id
        from    t2
        where   t1.id = t2.t1id
        order by
                name desc
        limit   1
        )

Beispiel bei SQL Fiddle.

Andomar
quelle
es ist sehr einfach und nützlich .. und funktioniert perfekt .. danke ..
deavega66
1

Fügen Sie eine LIMIT-Klausel hinzu, um die Anzahl der von einer (Unter-) Abfrage zurückgegebenen Zeilen zu begrenzen . Dies wird hier jedoch nicht benötigt, da in SQLite skalare Unterabfragen ein implizites LIMIT 1 haben.

Spaltenwerte von asind im Inneren nicht verfügbar, InvoiceRevisedda dies eine unabhängige Tabelle ist. Sie müssen den äußeren Join durch korrelierte Unterabfragen ersetzen, eine für jede Spalte:

SELECT id,
       CodeValue,
       TotalAmount,
       (SELECT Id
        FROM Invoices
        JOIN SCSInvoiceRels ON Invoices.Id = SCSInvoiceRels.InvoiceId
        WHERE SCSInvoiceRels.RecordStatus = 1
          AND Invoices.RecordStatus = 1
          AND SCSInvoiceRels.SCDetailId IN (SELECT SCDetailId
                                            FROM SCSInvoiceRels
                                            WHERE InvoiceId = a.id)
       ) AS RevisedInvoiceId,
       (SELECT /* there is no BillNumber in your InvoiceRevised ??? */
        FROM Invoices
        JOIN SCSInvoiceRels ON Invoices.Id = SCSInvoiceRels.InvoiceId
        WHERE SCSInvoiceRels.RecordStatus = 1
          AND Invoices.RecordStatus = 1
          AND SCSInvoiceRels.SCDetailId IN (SELECT SCDetailId
                                            FROM SCSInvoiceRels
                                            WHERE InvoiceId = a.id)
       ) AS RevisedInvoice,
       (SELECT pr.CodeValue
        FROM PatientRegs AS pr
        JOIN Patients AS pa ON pa.id = pr.PatientId
        JOIN SCDetails AS SC ON pr.id = SC.RegId
        JOIN SCSInvoiceRels AS SCb ON SC.id = SCb.SCDetailId
        WHERE SCb.InvoiceId = a.Id
       ) AS RegistrationNumber,
       (SELECT pa.Name
        FROM PatientRegs AS pr
        JOIN Patients AS pa ON pa.id = pr.PatientId
        JOIN SCDetails AS SC ON pr.id = SC.RegId
        JOIN SCSInvoiceRels AS SCb ON SC.id = SCb.SCDetailId
        WHERE SCb.InvoiceId = a.Id
       ) AS PatientName
FROM Invoices AS a
WHERE RecordStatus = 0
  AND UpdateOn IS NOT NULL
CL.
quelle