INNER JOIN与SELECT STATEMENT ISSUE

时间:2012-08-13 10:27:35

标签: mysql sql inner-join

我希望有人可以提供帮助,因为我现在已经尝试解决这个问题一段时间了,而且还遇到了一个非常小的问题。

通过以下查询,我主要尝试执行以下操作:

从订单中选择所有股票代码。

然后,找到每个股票代码存储在STOCK_LOCATIONS表中的所有位置。

然后,从STOCK_LOCATIONS表中返回一个位置。

但是,我需要交叉引用LOCATION_DATA表。 LOCATION_DATA表中的每个位置都有一个名为PICK的列,包含Y或N.我想返回Y为首选的位置,如果PICK列中没有Y,则返回N.

我实际上需要在Inner Join LOCATION_DATA查询中对结果进行排序,但这是不可能的。我已经尝试在INNER JOIN中添加一个SELECT语句(我认为这可能是最好的方法),但未能使它工作。

任何建议表示赞赏。 非常感谢...

SELECT
    STOCK_LOCATIONS.*,
    LOCATION_DATA.*,
    STOCK_DATA.PHYSICAL,
    ORDER_DATA.ENTRY,
    ORDER_DATA.STOCK,
    ORDER_DATA.ORDER_QTY,
    (SELECT
        COUNT(STOCK_LOCATIONS.location)
        FROM STOCK_LOCATIONS 
        WHERE ORDER_DATA.STOCK = STOCK_LOCATIONS.sku
        GROUP BY STOCK_LOCATIONS.sku
        HAVING COUNT(STOCK_LOCATIONS.sku) > 1
    ) AS RowCount
FROM ORDER_DATA
INNER JOIN STOCK_DATA
    ON ORDER_DATA.STOCK = STOCK_DATA.STOCK_CODE             
INNER JOIN STOCK_LOCATIONS
    ON ORDER_DATA.STOCK = STOCK_LOCATIONS.sku
INNER JOIN LOCATION_DATA
    ON STOCK_LOCATIONS.location = LOCATION_DATA.location
WHERE ORDER_DATA.ORDER_REF = '21254'    
GROUP BY ORDER_DATA.STOCK
ORDER BY LOCATION_DATA.pick_order ASC

这里有一些样本数据

和所需产出的例子

STOCK_LOCATIONS     
sku         location    
123456      A1  
123457      A2  
123459      C1  
123456      B1  
123457      B2  


LOCATION_DATA       
location    pick    
A1          Y   
A2          Y   
B1          N   
B2          N   
C1          N   


STOCK_DATA      
STOCK_CODE  PHYSICAL    
123456      10  
123457      0   
123459      100 


ORDER_DATA      
ENTRY   STOCK       ORDER_QTY
1       123456      10
2       123457      2
3       123459      1


RETURN DATA     
STOCK_CODE  ENTRY   LOCATION    PICK    ORDER_QTY   PHYSICAL    
123456      1       A1          Y       10          10
123457      2       A2          Y       2           0
123459      3       C1          N       1           100

这里有一个更新的尝试,因为它会导致与未知表格有关的错误:

// OPTION 1

SELECT
    STOCK_LOCATIONS.*,
    LOCATION_DATA.*,
    STOCK_DATA.PHYSICAL,
    ORDER_DATA.ENTRY,
    ORDER_DATA.STOCK,
    ORDER_DATA.ORDER_QTY,
    (SELECT
        COUNT(STOCK_LOCATIONS.location)
        FROM STOCK_LOCATIONS 
        WHERE ORDER_DATA.STOCK = STOCK_LOCATIONS.sku
        GROUP BY STOCK_LOCATIONS.sku
        HAVING COUNT(STOCK_LOCATIONS.sku) > 1
    ) AS RowCount,
    (SELECT 
        CASE
            WHEN dat1.pick IS NOT NULL THEN loc1.location
            ELSE loc2.location 
        END
    ) AS location

FROM ORDER_DATA
INNER JOIN STOCK_DATA
    ON ORDER_DATA.STOCK = STOCK_DATA.STOCK_CODE

LEFT JOIN STOCK_LOCATIONS loc1
    ON ORDER_DATA.STOCK = loc1.sku

LEFT JOIN LOCATION_DATA dat1
    ON loc1.location = dat1.location
    AND dat1.pick = 'Y'

LEFT JOIN STOCK_LOCATIONS loc2
    ON ORDER_DATA.STOCK = loc2.sku

LEFT JOIN STOCK_LOCATIONS dat2
    ON loc2.location = dat2.location
    AND dat1.pick = 'N'

WHERE ORDER_DATA.ORDER_REF = '".$_GET_q."'  
GROUP BY ORDER_DATA.STOCK
ORDER BY LOCATION_DATA.pick_order ASC

// OPTION 2

SELECT
    STOCK_LOCATIONS.*,
    LOCATION_DATA.*,
    STOCK_DATA.PHYSICAL,
    ORDER_DATA.ENTRY,
    ORDER_DATA.STOCK,
    ORDER_DATA.ORDER_QTY,
    (SELECT
        COUNT(STOCK_LOCATIONS.location)
        FROM STOCK_LOCATIONS 
        WHERE ORDER_DATA.STOCK = STOCK_LOCATIONS.sku
        GROUP BY STOCK_LOCATIONS.sku
        HAVING COUNT(STOCK_LOCATIONS.sku) > 1
    ) AS RowCount

FROM ORDER_DATA
INNER JOIN STOCK_DATA
    ON ORDER_DATA.STOCK = STOCK_DATA.STOCK_CODE

JOIN STOCK_LOCATIONS loc1
    ON ORDER_DATA.STOCK = loc1.sku

JOIN LOCATION_DATA dat1
    ON loc1.location = dat1.location 
    AND dat1.pick = CASE WHEN EXISTS
    (SELECT
        *
        FROM STOCK_LOCATIONS loc2
        JOIN LOCATION_DATA dat2
            ON loc2.location = dat2.location
            AND dat1.pick = 'Y'
        WHERE ORDER_DATA.STOCK = loc2.sku
    )
    THEN 'Y' ELSE 'N' END

WHERE ORDER_DATA.ORDER_REF = '".$_GET_q."'  
GROUP BY ORDER_DATA.STOCK
ORDER BY LOCATION_DATA.pick_order ASC

// OPTION 3

SELECT
    STOCK_LOCATIONS.*,
    LOCATION_DATA.*,
    STOCK_DATA.PHYSICAL,
    ORDER_DATA.ENTRY,
    ORDER_DATA.STOCK,
    ORDER_DATA.ORDER_QTY,

    (SELECT
        COUNT(STOCK_LOCATIONS.location)
        FROM STOCK_LOCATIONS 
        WHERE ORDER_DATA.STOCK = STOCK_LOCATIONS.sku
        GROUP BY STOCK_LOCATIONS.sku
        HAVING COUNT(STOCK_LOCATIONS.sku) > 1
    ) AS RowCount,

    (SELECT 
            STOCK_LOCATIONS.location
            FROM STOCK_LOCATIONS 
            INNER JOIN LOCATION_DATA
                ON STOCK_LOCATIONS.location = LOCATION_DATA.location
            WHERE ORDER_DATA.STOCK = STOCK_LOCATIONS.sku
            ORDER BY pick DESC, rand()
            LIMIT 1
    ) AS location

FROM ORDER_DATA

INNER JOIN STOCK_DATA
    ON ORDER_DATA.STOCK = STOCK_DATA.STOCK_CODE             

INNER JOIN STOCK_LOCATIONS
    ON ORDER_DATA.STOCK = STOCK_LOCATIONS.sku

INNER JOIN LOCATION_DATA
    ON STOCK_LOCATIONS.location = LOCATION_DATA.location

WHERE ORDER_DATA.ORDER_REF = '".$_GET_q."'  
GROUP BY ORDER_DATA.STOCK
ORDER BY LOCATION_DATA.pick_order ASC   

2 个答案:

答案 0 :(得分:0)

您可以加入位置表两次,一次是针对pick = 'Y'的行,一次是针对pick = 'N'的行。然后你可以使用case语句来优先考虑第一个,但是回到第二个:

SELECT  case
        when dat1.pick is not null then loc1.location
        else loc2.location 
        end as Location
....
LEFT JOIN 
        STOCK_LOCATIONS loc1
ON      ORDER_DATA.STOCK = loc1.sku
LEFT JOIN
        LOCATION_DATA dat1
ON      loc1.location = dat1.location
        AND dat1.pick = 'Y'
LEFT JOIN
        STOCK_LOCATIONS loc2
ON      ORDER_DATA.STOCK = loc2.sku
LEFT JOIN
        LOCATION_DATA dat2
ON      loc2.location = dat2.location
        AND dat1.pick = 'N'

另一个选项是带子查询的连接条件。子查询可以查找存在pick = 'Y'的位置,否则返回pick = 'N'

JOIN    STOCK_LOCATIONS loc1
ON      ORDER_DATA.STOCK = loc1.sku
JOIN    LOCATION_DATA dat1
ON      loc1.location = dat1.location 
        AND dat1.pick = case when exists
        (
        select  *
        from    STOCK_LOCATIONS loc2
        JOIN    LOCATION_DATA dat2
        ON      loc2.location = dat2.location
                AND dat1.pick = 'Y'
        WHERE   ORDER_DATA.STOCK = loc2.sku
        )
        then 'Y' else 'N' end

答案 1 :(得分:0)

我认为您可以在select子句中将其作为子查询执行:

SELECT STOCK_LOCATIONS.*, LOCATION_DATA.*, STOCK_DATA.PHYSICAL,
       ORDER_DATA.ENTRY, ORDER_DATA.STOCK, ORDER_DATA.ORDER_QTY, 
       (SELECT COUNT(STOCK_LOCATIONS.location) 
        FROM STOCK_LOCATIONS  
        WHERE ORDER_DATA.STOCK = STOCK_LOCATIONS.sku   
        GROUP BY STOCK_LOCATIONS.sku  
        HAVING COUNT(STOCK_LOCATIONS.sku) > 1
       ) AS RowCount,
       (SELECT STOCK_LOCATIONS.location
        FROM STOCK_LOCATIONS  
        WHERE ORDER_DATA.STOCK = STOCK_LOCATIONS.sku
        order by pick desc, rand()
        limit 1
       ) AS ChosenLocation

这会选择一行的相关子查询。它命令它们适合您想要的业务逻辑。如果您想了解有关该位置的更多信息,我会将其放入子查询中并加入其他信息。