簡體   English   中英

排除特定列中的多個結果(SQL JOIN)

[英]Excluding multiple results in specific column (SQL JOIN)

我正在實際生活中使用SQL方面邁出第一步。

我有一些包含合同和財務信息的表,並且查詢在某種程度上完全可以滿足我的需要。 看起來或多或少是這樣的:

SELECT /some columns/ from CONTRACTS

用INNER JOIN鏈接了3 extra tables ,以添加諸如部門名稱,產品信息等內容。這一切都可行,但是它們都具有簡單的一對一關系(在Department表中有一個與單個部門相關的合同,在對應的表中有一個產品信息條目表等)。

現在這是我的挑戰:

我還需要添加合同發票信息,例如:

inner join INVOICES on CONTRACTS.contnoC = INVOICES.contnoI

(並選擇鏈接到Contract numberInvoice number Contract number ,盡管這是部分可選的)

我面臨的問題是,與其他表不同, INVOICES表時總是存在一對一的關系, INVOICES表可以有多個(或根本沒有)對應於單個合同編號的條目。 結果是,我將獲得單個合同編號(顯示不同發票編號)的多個查詢結果,從而不必要地擁擠了查詢結果。

本質上,我希望將INVOICES表添加到查詢中,以僅識別INVOICES表中是否存在合同編號(合同是否已開具發票)。 發票編號本身可以顯示(與INNER JOIN ),但是並不重要,只要它以某種方式被標記即可。 使用INNER JOIN函數的結果中的Invoice number字段保持空白,這也是必須的(即,即使在INVOICES表中找不到匹配項,也要顯示行)。

SELECT DISTINCT我的需要,但是我似乎面臨這樣一個問題,我只需要對代表合同編號的列而不是任何其他列征收DISTINCT標准(可以提供相同的值,但是應該提供所有這些值) 。

不幸的是,我並不完全知道我使用的是哪個數據庫系統。

我會這樣:

with mainquery as(
<<here goes you main query>>
),

invoices_rn as( 
select *, 
ROW_NUMBER() OVER (PARTITION BY contnoI order by 
<<some column to decide which invoice you want to take eg. date>>) as rn
)

invoices as (
select * from invoices_rn where rn = 1
)

select * from mainquery
left join invoices i on contnoC = i.contnoI

這使您能夠將所有發票詳細信息都添加到查詢中,還可以完全控制要在主查詢中看到的發票。 請閱讀有關CTE的更多信息; 它們非常方便,比嵌套選擇更易於理解/閱讀。

我仍然不知道您正在使用哪個數據庫。 如果ROW_NUMBER不可用,我會找出其他的方法:)

同樣,如果使用左聯接,則應使用COALESCE函數,例如:

COALESCE(i.invoice_number,'0')

當然,這為您提供了更多可能性,例如,您可以在主選擇中執行以下操作:

CASE WHEN i.invoicenumber is null then 'NOT INVOICED'
else 'INVOICED'
END as isInvoiced

似乎這個問題仍在引起人們的注意,為了提供一些解釋,這里提供了一些技巧。

如果您只需要合同中包含從1到1表格中的詳細信息,則可以按照所描述的類似方式進行操作。 關鍵是不要在列列表中包含“發票”表中的任何列。

SELECT
   DISTINCT Contract, Department, ProductId .....(nothing from Invoices Table!!!)
FROM
    Contracts c
    INNER JOIN Departments D
    ON c.departmentId = d.Department
    INNER JOIN Product p
    ON c.ProductId = p.ProductId
    INNER JOIN Invoices i
    ON c.contnoC  = i.contnoI

也許更干凈一點的是使用IN或EXISTS,如下所示:

SELECT
   Contract, Department, ProductId .....(nothing from Invoices Table!!!)
FROM
    Contracts c
    INNER JOIN Departments D
    ON c.departmentId = d.Department
    INNER JOIN Product p
    ON c.ProductId = p.ProductId
WHERE
    EXISTS (SELECT 1 FROM Invoices i WHERE i.contnoI = c.contnoC )

SELECT
   Contract, Department, ProductId .....(nothing from Invoices Table!!!)
FROM
    Contracts c
    INNER JOIN Departments D
    ON c.departmentId = d.Department
    INNER JOIN Product p
    ON c.ProductId = p.ProductId
WHERE
    contnoC IN (SELECT contnoI FROM Invoices)

如果SELECT ...列表可以返回NULL不要使用IN!

如果您實際上想要所有合同,並且只知道合同是否已開票,則可以使用聚合和大小寫表達式:

SELECT
   Contract, Department, ProductId, CASE WHEN COUNT(i.contnoI) = 0 THEN 0 ELSE 1 END as Invoiced
FROM
    Contracts c
    INNER JOIN Departments D
    ON c.departmentId = d.Department
    INNER JOIN Product p
    ON c.ProductId = p.ProductId
    LEFT JOIN Invoices i
    ON c.contnoC  = i.contnoI
GROUP BY
    Contract, Department, ProductId

然后,如果您實際上想返回有關特定發票的詳細信息,則可以使用與Cyber​​centic87類似的技術(如果RDBMS支持),或者可以根據系統使用帶TOPLIMIT的計算列。

SELECT
   Contract, Department, ProductId, (SELECT TOP 1 InvoiceNo FROM invoices i WHERE c.contnoC  = i.contnoI ORDER BY CreateDate DESC) as LastestInvoiceNo
FROM
    Contracts c
    INNER JOIN Departments D
    ON c.departmentId = d.Department
    INNER JOIN Product p
    ON c.ProductId = p.ProductId
GROUP BY
    Contract, Department, ProductId

您可以使用SELECT ...,開票='是'...存在的地方...聯合SELECT ...,開票='否'...不存在的地方...

或者您可以將帶有“發票”的列與子查詢一起使用到發票中,以根據您是否點擊匹配項來設置其值

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM