简体   繁体   English

如何在一列中正确联接MSsql中的四个表?

[英]How do I correctly join four tables in MSsql on one column?

I'm trying to join four separate queries on "PROD_CD" to return the correct output into one query to prevent having to merge the queries together in another language after. 我试图在“ PROD_CD”上加入四个单独的查询,以将正确的输出返回到一个查询中,以防止以后不得不将另一种语言的查询合并在一起。 With the current one (and I've tried many variations, all with various problems), I'm receiving a lot of duplicate results and different numbers of duplicates for each. 对于当前版本(我已经尝试了许多变体,都遇到了各种问题),我收到了很多重复的结果,并且每个重复结果的数量都不相同。

Here's the current query I've been trying (all the date functions are for determining dataset over a span of time - the database is very old and uses Clarion time): 这是我一直在尝试的当前查询(所有日期函数均用于确定一段时间内的数据集-数据库非常旧,并使用号角时间):

$query_ats = "SELECT 
            plog.prod_cd as prod_id,
            ord_log.ORDER_QTY as total_so,
            ediordlg.ORDER_QTY as total_edi_so,
            inv_data.IN_STOCK as in_stock
        FROM plog 
        INNER JOIN ord_log 
            ON plog.prod_cd = ord_log.prod_cd 
        INNER JOIN ediordlg 
            ON plog.prod_cd = ediordlg.prod_cd AND ord_log.prod_cd = ediordlg.prod_cd
        INNER JOIN inv_data 
            ON plog.prod_cd = inv_data.prod_cd AND ord_log.prod_cd = inv_data.prod_cd AND ediordlg.prod_cd = inv_data.prod_cd
        WHERE 
            inv_data.CLASS_CD = 'ALG7' 
        AND 
            dateadd(day, plog.EST_DT, '18001228') BETWEEN getdate() and dateadd(day, $x, getdate())
        AND 
            dateadd(day, ord_log.SHIP_DT, '18001228') BETWEEN getdate() and dateadd(day, $x, getdate())
        AND 
            dateadd(day, ediordlg.SHIP_DT, '18001228') BETWEEN getdate() and dateadd(day, $x, getdate())
        GROUP BY plog.prod_cd, plog.log_qty, ord_log.ORDER_QTY, ediordlg.ORDER_QTY, inv_data.IN_STOCK
        ORDER BY plog.prod_cd ASC";

And this is a sample of what it outputs: 这是其输出的示例:

Array ( [prod_id] => ALG-809 阵列([prod_id] => ALG-809
[total_so] => 4 [total_edi_so] => 46 [in_stock] => 0 ) Array ( [prod_id] => ALG-809 [total_so] => 4 [total_edi_so] => 46 [in_stock] => 0)数组([prod_id] => ALG-809
[total_so] => 6 [total_edi_so] => 46 [in_stock] => 0 ) Array ( [prod_id] => ALG-809 [total_so] => 6 [total_edi_so] => 46 [in_stock] => 0)数组([prod_id] => ALG-809
[total_so] => 7 [total_edi_so] => 46 [in_stock] => 0 ) [total_so] => 7 [total_edi_so] => 46 [in_stock] => 0)

Here are the four separate queries that return the correct results: 这是四个返回正确结果的独立查询:

$query_stock = "SELECT 
                prod_cd, 
                inv_data.DESCRIP,
                inv_data.IN_STOCK
            from 
                inv_data 
            where 
                inv_data.CLASS_CD = 'ALG7'
            ORDER BY
                inv_data.prod_cd ASC";

$query_po = "SELECT 
            plog.prod_cd, 
            SUM(plog.log_qty) as total_po
        FROM 
            plog JOIN inv_data ON plog.prod_cd = inv_data.prod_cd 
        WHERE 
            inv_data.CLASS_CD = 'ALG7'
        AND 
            dateadd(day, EST_DT, '18001228') BETWEEN getdate() and dateadd(day, $x, getdate())
        GROUP BY 
            plog.prod_cd
        ORDER BY
            plog.prod_cd ASC";

$query_so = "SELECT 
            ord_log.prod_cd,
            SUM(ord_log.ORDER_QTY) as total_so
        FROM 
            ord_log JOIN inv_data ON ord_log.prod_cd = inv_data.prod_cd 
        WHERE 
            inv_data.CLASS_CD = 'ALG7' 
        AND 
            dateadd(day, SHIP_DT, '18001228') BETWEEN getdate() and dateadd(day, $x, getdate()) 
        GROUP BY 
            ord_log.PROD_CD
        ORDER BY
            ord_log.prod_cd ASC";

$query_edi = "SELECT 
            ediordlg.prod_cd,
            SUM(ediordlg.ORDER_QTY) as total_so_EDI
        FROM
            ediordlg JOIN inv_data ON ediordlg.prod_cd = inv_data.prod_cd 
        WHERE 
            inv_data.CLASS_CD = 'ALG7' 
        AND 
            dateadd(day, SHIP_DT, '18001228') BETWEEN getdate() and dateadd(day, $x, getdate()) 
        GROUP BY 
            ediordlg.PROD_CD
        ORDER BY
            ediordlg.prod_cd ASC";

I'm sure it's the JOIN I'm using but I can't figure it out for the life of me. 我确定这是我正在使用的JOIN,但我一生都无法解决。 Any suggestions? 有什么建议么? Thanks! 谢谢!

why not use a DISTINCT ? 为什么不使用DISTINCT

$query_ats = "SELECT DISTINCT
            plog.prod_cd as prod_id,
            ord_log.ORDER_QTY as total_so,
            ediordlg.ORDER_QTY as total_edi_so,
            inv_data.IN_STOCK as in_stock
        FROM plog 
        INNER JOIN ord_log 
            ON plog.prod_cd = ord_log.prod_cd 
        INNER JOIN ediordlg 
            ON plog.prod_cd = ediordlg.prod_cd AND ord_log.prod_cd = ediordlg.prod_cd
        INNER JOIN inv_data 
            ON plog.prod_cd = inv_data.prod_cd AND ord_log.prod_cd = inv_data.prod_cd AND ediordlg.prod_cd = inv_data.prod_cd
        WHERE 
            inv_data.CLASS_CD = 'ALG7' 
        AND 
            dateadd(day, plog.EST_DT, '18001228') BETWEEN getdate() and dateadd(day, $x, getdate())
        AND 
            dateadd(day, ord_log.SHIP_DT, '18001228') BETWEEN getdate() and dateadd(day, $x, getdate())
        AND 
            dateadd(day, ediordlg.SHIP_DT, '18001228') BETWEEN getdate() and dateadd(day, $x, getdate())
        GROUP BY plog.prod_cd, plog.log_qty, ord_log.ORDER_QTY, ediordlg.ORDER_QTY, inv_data.IN_STOCK
        ORDER BY plog.prod_cd ASC";

Rule 1 of SQL in cases like this: Select initially from the thing that you want rows out of, join to the things you want more information about. 在这种情况下,SQL规则1:首先从要从中删除行的对象中选择,然后加入要获取更多信息的对象。 In your case what you want seems to be the product ID and this seems to be uniquely stored in the inv_data table, so we'll start with that. 在您的情况下,您想要的似乎是产品ID,并且似乎唯一地存储在inv_data表中,因此我们inv_data开始。

select
        i.prod_cd as product,
        i.descrip as description,
        i.in_stock
    from
        inv_data as i
    where
        i.class_cd = 'ALG7'
    order by
        i.prod_cd asc
;

You'll get one of each because only one of each is stored. 您将获得每个,因为只存储一个。 The rest is just details. 剩下的只是细节。 Let's add some joins 让我们添加一些联接

select
        i.prod_cd as product,
        i.descrip as description,
        i.in_stock,
        sum(l.order_qty) as l_total_so,
        sum(e.order_qty) as e_total_so
    from
        inv_data as i
        inner join plog as p
            on i.prod_cd = p.prod_cd
        inner join ord_log as l
            on i.prod_cd = l.prod_cd
        inner join ediordlg as e
            on i.prod_cd = e.prod_cd
    where
        i.class_cd = 'ALG7'
    order by
        i.prod_cd asc
    group by
        i.prod_cd,
        i.descrip,
        i.in_stock
;

You don't need to list so many columns in your on clauses because they're all the same anyway (by definition, because the earlier inner join succeeded). 您不必在on子句中列出太多列,因为它们无论如何都是相同的(根据定义,因为较早的内部连接成功)。

If it turns out that plog and not inv_data is your master table simply reverse them in the query. 如果事实证明plog而不是inv_data是您的主表,只需在查询中将它们反向即可。 If you want both total values together, use sum(l.order_qty + e.order_qty) as total_so instead of creating two columns. 如果要同时将两个总值一起使用,请使用sum(l.order_qty + e.order_qty) as total_so而不是创建两列。

The thing to understand is that joins can multiply the results. 要了解的是联接可以使结果成倍增加。 Understanding which tables have more and doing something in each case to limit the "extra" results each time they would be extra will result in a clean resultset. 了解哪些表有更多的表,并在每种情况下都要做一些事情以限制“额外”结果,这将产生干净的结果集。 In this case probably just summing and grouping is enough, but in a complex case you would need to join to a sub-query that selects back a sufficiently distinct set. 在这种情况下,仅求和和分组可能就足够了,但是在复杂的情况下,您需要加入一个子查询,该子查询会选择足够不同的集合。

And, on a related note, distinct is poison for your query! 而且,与此相关的, distinct是毒药您的查询! It has a very specific purpose which is not to fix "too many duplicate rows after joining." 它有一个非常特定的目的,即不会修复“连接后有太多重复的行”。 If you're using it for that you probably have a bug that could have unknown other side effects. 如果将其用于此目的,则可能是一个可能具有未知其他副作用的错误。 Try to fix it with group by and smarter on statements first, then nested queries. 尝试先使用group by和更聪明on语句来解决它,然后再嵌套查询。

Not related to your question, but important: It appears that you are expanding a variable $x inside your query. 与您的问题无关,但很重要:看来您正在查询中扩展变量$x This is probably not safe (or efficient); 这可能不安全(或高效); try to use a parametrized query instead. 尝试改用参数化查询。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM