我在现实生活中使用实际SQL的第一步。
我有一些包含合同和财务信息的表格,并且查询完全符合我的需要 - 在某一点上。看起来或多或少是这样的:
SELECT /some columns/ from CONTRACTS
将链接3 extra tables
与INNER JOIN联系以添加部门名称,产品信息等内容。这一切都有效,但它们都有简洁的一对一关系(与Department
中的单个部门相关的一个合同表,相应表格中的一个产品信息条目等。)
现在这是我的挑战:
我还需要添加合同发票信息,例如:
inner join INVOICES on CONTRACTS.contnoC = INVOICES.contnoI
(并选择与Invoice number
相关联的Contract number
,但这部分可选)
我遇到的问题是,与其他表连接表时始终存在一对一的关系不同,INVOICES
表可以有多个(或根本没有)条目对应单一合同号。结果是,我将获得单个合同no的多个查询结果(显示不同的发票号),不必要地拥挤查询结果。
基本上我希望将INVOICES
表添加到查询中,以确定INVOICES
表中是否存在合同no(合同是否已开票)。可以显示发票号码本身(它是INNER JOIN
),但只要它以某种方式标记,它就不重要。 Invoice number
函数在结果中保留INNER JOIN
个字段,这也是必要的(即即使在INVOICES
表中找不到匹配也会显示该行)。
SELECT DISTINCT
会做我需要做的事情,但我似乎面临的问题是,我只需要为代表合同编号的列征收DISTINCT
条件,而不是任何其他列(可以有相同的提出的价值,但所有这些都应该出现。)
不幸的是,我并不完全了解我正在使用的数据库系统。
答案 0 :(得分:1)
我会这样做:
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)
似乎问题仍然得到一些关注,并且努力提供一些解释,这里有一些技巧。
如果您只想要与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
!!!
如果您实际上想要所有合同并且只知道合同是否已开具发票,您可以使用聚合和案例表达:
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
然后,如果您确实想要返回有关特定发票的详细信息,则可以使用类似于cybercentic87的技术(如果您的RDBMS支持),或者您可以使用带有TOP
或LIMIT
的计算列,具体取决于你的系统。
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
答案 2 :(得分:-1)
你可以使用 SELECT ...,发票=&#39;是&#39; ......存在的地方...... 联盟 SELECT ...,发票=&#39;否&#39; ......哪里不存在......
或者您可以使用&#34;发票&#34;等列。使用子查询到发票中,根据您是否受到打击来设置其值