使用 join 语句连接子查询

Posted

技术标签:

【中文标题】使用 join 语句连接子查询【英文标题】:Joining a subquery with a join statement 【发布时间】:2018-08-31 19:54:38 【问题描述】:

尝试将子查询应用于表以便能够对其进行分组。

主查询

 SELECT soitem.fsono, fpartno, soitem.fcfromno, finumber
 FROM soitem 
 INNER JOIN somast on soitem.fsono = somast.fsono  
 WHERE somast.fsono='034313'  
 ORDER by soitem.fsono, soitem.finumber

子查询

SELECT min(sq.finumber), sq.fcfromno 
FROM soitem sq 
WHERE sq.fsono='034313' 
GROUP BY sq.fcfromno   

我想使用min_finumber 进一步对我的数据集进行分组。这应该显示为三行。我使用原始问题将子查询合并到我的整体代码中。我的主要目标是能够成功地将 min_number 分组

SELECT somast.fsono, 
somast.fcustno, 
somast.fcontact, 
somast.fcustpono, 
somast.fshipvia, 
somast.forderdate, 
somast.fduedate,
 soship.fccompany, 
 soship.fcphone, 
  REPLACE(REPLACE(CONVERT(VARCHAR(MAX), soship.fmstreet), CHAR(13), '|'), CHAR(10), ' ') AS Street,
soship.fccity,
 soship.fcstate, 
 soship.fczip,
 CAST(somast.fackmemo as CHAR(35)) as ShipCode, 
 somast.fordername,
  somast.fcusrchr2,
somast.fcusrchr3,
somast.fcusrchr1, 
somast.festimator, 
soitem.fcfromno, 
 soitem.fcfromtype,
  CASE WHEN soitem.fcfromtype <> 'IFPKIT' THEN soitem.fpartno ELSE soitem.fcfromno END AS Item, 
 CASE WHEN soitem.fcfromtype <> 'IFPKIT' THEN soitem.fquantity ELSE soitem.fquantity / soitem.fquoteqty END AS Qty, 
CASE WHEN soitem.fcfromtype <> 'IFPKIT' 
THEN CAST(soitem.fdesc as CHAR(35))
ELSE 'Store Set (Phantom)' END as Descr

FROM soitem INNER JOIN
 somast ON soitem.fsono = somast.fsono LEFT OUTER JOIN
 soship ON somast.fsono = soship.fcsono AND soship.fcenumber = ''

WHERE   
(somast.fstatus <> 'Cancelled') AND (somast.fsocoord = 'IFP' OR
 somast.fsocoord = '711')
 Group By REPLACE(REPLACE(CONVERT(VARCHAR(MAX), soship.fmstreet), CHAR(13), '|'), CHAR(10), ' '),
 CAST(somast.fackmemo as CHAR(35)),
 somast.fsono,
somast.fcustno,
fcontact,
fcustpono,
fshipvia,
forderdate,
somast.fduedate,

CASE WHEN soitem.fcfromtype<>'IFPKIT' 
THEN soitem.fpartno 
ELSE soitem.fcfromno END,

CASE WHEN soitem.fcfromtype<>'IFPKIT' 
THEN soitem.fquantity 
ELSE soitem.fquantity/soitem.fquoteqty END,

CASE WHEN soitem.fcfromtype <> 'IFPKIT' 
THEN CAST(soitem.fdesc as CHAR(35))
ELSE 'Store Set (Phantom)' END,

soship.fccity, 
soship.fcstate, 
soship.fczip,
fordername, 
fcusrchr2, 
fcusrchr3,
 fcusrchr1, 
festimator,
soitem.fcfromno, 
soitem.fcfromtype,
 soship.fccompany,
  soship.fcphone

ORDER BY somast.forderdate, somast.fsono, soitem.fcfromno

【问题讨论】:

请解释“将子查询应用于表”是什么意思。样本数据和所需结果的帮助。 所以看起来您正在尝试在soitem 表中找到当前行的finumber 和最小值finumber,对吗? 是的,这是正确的。我一直在尝试使用 fsono+finumber 加入他们。 您想要最小的finumberfcfrom,即使没有soitem 匹配到somast 表还是只匹配记录的最小值? fpartnofinumberSELECT coming from the soitem` 表或somast 表中吗? 【参考方案1】:

由于您使用的是 SQL Server 2008 R2,因此您可以访问所需的窗口函数。尝试类似:

SQL Fiddle

SQL Server 2017 架构设置:

CREATE TABLE soitem 
(
     fsono INT, 
     fpartno INT,
     soitem INT, 
     finumber INT, 
     fcfromno INT
);

INSERT INTO soitem (fsono, fpartno, soitem, finumber, fcfromno)
VALUES (1, 1, 1, 1, 1), (1, 2, 2, 5, 1), 
       (2, 2, 2, 9, 2), (2, 2, 2, 2, 2),
       (3, 2, 2, 1, 9);

CREATE TABLE somast (fsono int) ;

INSERT INTO somast (fsono)
VALUES (1), (2);

主要查询:

SELECT 
    soitem.fsono,
    soitem.fpartno,
    soitem.fcfromno,
    soitem.finumber,
    /* THE BELOW PART IS YOUR "JOIN" */
    MIN(soitem.finumber) OVER (PARTITION BY soitem.fsono, soitem.fcfromno) AS min_finumber
FROM 
    soitem 
INNER JOIN 
    somast ON soitem.fsono = somast.fsono  
WHERE 
    somast.fsono = '1'
ORDER BY
    soitem.fsono, soitem.finumber

Results:

| fsono | fpartno | fcfromno | finumber | min_finumber |
|-------|---------|----------|----------|--------------|
|     1 |       1 |        1 |        1 |            1 |
|     1 |       2 |        1 |        5 |            1 |

您的主要查询:

SELECT soitem.fsono, fpartno, soitem.fcfromno, finumber
FROM soitem 
INNER JOIN somast on soitem.fsono = somast.fsono  
WHERE somast.fsono='1'  
ORDER by soitem.fsono, soitem.finumber

Results

| fsono | fpartno | fcfromno | finumber |
|-------|---------|----------|----------|
|     1 |       1 |        1 |        1 |
|     1 |       2 |        1 |        5 |

您的子查询

SELECT min(sq.finumber), sq.fcfromno 
FROM soitem sq 
WHERE sq.fsono='1' 
GROUP BY sq.fcfromno

Results

|   | fcfromno |
|---|----------|
| 1 |        1 |

【讨论】:

这得到了我需要的结果,但我无法 GROUP BY min_finumber min_finumberGROUP BY 运行时不存在。本质上,SQL 查询的逻辑过程如下:FROM &gt; WHERE &gt; GROUP BY &gt; HAVING &gt; SELECT &gt; DISTINCT &gt; ORDER BY &gt; TOP。如果您需要GROUP BYmin_finumber,则将该查询包含在另一个子查询中。你想用新的GROUP BY 做什么?可能有更好的方法来获得你最终想要的东西。 我希望能够在Select 语句的所有字段中找到min_finumber' so I can group it because they're is duplicate data . I'm using a Group By`。 复制了什么? soitemsomast 之间有多个匹配项?您可以更严格地过滤您的JOIN,以免重复。如果您可以为两个重复的表提供示例数据示例,我可以调整我的查询。 那么您如何为第二个GROUP BY 进行聚合?您需要 3 行,但这些组由不同的 fpartno 组成。您能否提供一个预期结果的样本,并说明您预期这些结果的原因?似乎在某个地方缺少一个步骤或一个组来获取您需要的数据。【参考方案2】:

我最终没有使用连接或子查询。通过将min(finumber) as min_fin 添加到SELECTORDER BY,我能够获得所需的结果

select soitem.fsono, 
somast.fcustno, 
somast.fcontact, 
somast.fcustpono, 
somast.fshipvia, 
somast.forderdate, 
somast.fduedate,
 soship.fccompany, 
 soship.fcphone, 
REPLACE(REPLACE(CONVERT(VARCHAR(MAX), soship.fmstreet), CHAR(13), '|'), CHAR(10), ' ') AS Street,
soship.fccity,
 soship.fcstate, 
 soship.fczip,
CAST(somast.fackmemo as CHAR(35)) as ShipCode,
CASE WHEN soitem.fcfromtype <> 'IFPKIT' THEN soitem.fpartno ELSE soitem.fcfromno END AS Item, 
CASE WHEN soitem.fcfromtype <> 'IFPKIT' THEN soitem.fquantity ELSE soitem.fquantity / soitem.fquoteqty END AS Qty, 
CASE WHEN soitem.fcfromtype <> 'IFPKIT' 
THEN CAST(soitem.fdesc as CHAR(35))
ELSE 'Store Set (Phantom)' END as Descr,
somast.fordername,
  somast.fcusrchr2,
somast.fcusrchr3,
somast.fcusrchr1, 
somast.festimator, 
soitem.fcfromno, 
soitem.fcfromtype, 

**min(finumber)as min_fin** 

from soitem INNER JOIN
 somast ON soitem.fsono = somast.fsono
 LEFT OUTER JOIN
 soship ON somast.fsono = soship.fcsono AND soship.fcenumber = ''

  where soitem.fsono='034313' 

group by soitem.fsono, CASE WHEN soitem.fcfromtype <> 'IFPKIT' THEN soitem.fpartno ELSE soitem.fcfromno END, 
soitem.fcfromno, soitem.fcfromtype,
somast.fcustno, 
somast.fcontact, 
somast.fcustpono, 
somast.fshipvia, 
somast.forderdate, 
somast.fduedate,
 soship.fccompany, 
 soship.fcphone,
 REPLACE(REPLACE(CONVERT(VARCHAR(MAX), soship.fmstreet), CHAR(13), '|'), CHAR(10), ' '),
soship.fccity,
 soship.fcstate, 
 soship.fczip,
 CAST(somast.fackmemo as CHAR(35)),
 CASE WHEN soitem.fcfromtype <> 'IFPKIT' THEN soitem.fquantity ELSE soitem.fquantity / soitem.fquoteqty END , 
CASE WHEN soitem.fcfromtype <> 'IFPKIT' 
THEN CAST(soitem.fdesc as CHAR(35))
ELSE 'Store Set (Phantom)' END, 
 somast.fordername,
  somast.fcusrchr2,
somast.fcusrchr3,
somast.fcusrchr1, 
somast.festimator

order by soitem.fsono, **min_fin**;

【讨论】:

以上是关于使用 join 语句连接子查询的主要内容,如果未能解决你的问题,请参考以下文章

子查询与关联查询区别

使用join语句加入子查询

子查询或连接?

JOIN 替代 SELECT 子查询

表的基本查询语句及使用连表(inner joinleft join)子查询

Mysql优化系列之——优化器对子查询的处理