MYSQL 联接查询多个表显示某些字段的重复结果


MYSQL Join Query Multiple Tables displays duplicate results for some fields

我正在 mysql 查询中连接表,它给了我重复的结果,因为在其中一个表上有 2 个结果。

这是我的查询。

$query_order = "
SELECT sfo.entity_id, sfo.status, sfo.created_at, sfo.customer_firstname, sfo.customer_lastname, sfo.customer_email, sfo.subtotal, sfo.shipping_amount, sfo.tax_amount, sfo.grand_total, sfo.total_paid, sfo.total_due, sfo.total_item_count,
sfoa.address_type, sfoa.firstname, sfoa.lastname, sfoa.street, sfoa.city, sfoa.region, sfoa.postcode, sfoa.telephone, sfoa.country_id,
sfoi.product_id, sfoi.name, sfoi.sku, sfoi.qty_ordered, sfoi.price, sfoi.original_price, sfoi.row_total, sfoi.additional_data as additional_data1,
sfst.track_number, sfst.carrier_code, sfst.title,
sfop.additional_data as additional_data2, sfop.amount_paid, sfop.amount_ordered
FROM sales_flat_order sfo
JOIN sales_flat_order_address sfoa
ON sfo.entity_id = sfoa.parent_id
JOIN sales_flat_order_item sfoi
ON sfo.entity_id = sfoi.order_id
JOIN sales_flat_shipment_track sfst
ON sfo.entity_id = sfst.order_id
JOIN sales_flat_order_payment sfop
ON sfo.entity_id = sfop.entity_id
WHERE sfo.increment_id = '" . $po . "'
LIMIT 0 , 30";

sales_flat_order_addressparent_id有 2 个结果,因为其中一个是账单地址,另一个是送货地址。这两个字段具有相同的parent_id值,这就是我加入表的内容。

所有表都使用sales_flat_order sfo中的相同值进行联接,该值是entity_id,并且是该表的主键。

如何确保其他表仅从其字段中输出一次值,同时确保我仍然从表中获取sales_flat_order_address帐单和送货地址?

我尝试了 GROUP BY,它确实消除了重复项,但它也消除了sales_flat_order_address表中的送货地址。

我应该使用子查询来构建查询吗?我已经做了很多搜索,但到目前为止,我不确定如何处理我的具体情况。

更新 5/7/2016

为了允许显示帐单和送货地址,并且不从其他连接的表中复制其他字段,我必须做的是简单地连接地址表两次,以便while循环仅循环一次而不是两次。

所以我把它添加到我的SELECT

sfoab.address_type as billing, sfoab.firstname as bfirst, sfoab.lastname as blast, sfoab.street as bstreet, sfoab.city as bcity, sfoab.region as bregion, sfoab.postcode as bzip, sfoab.telephone as btel, sfoab.country_id as bcountry,
sfoas.address_type as shipping, sfoas.firstname as sfirst, sfoas.lastname as slast, sfoas.street as sstreet, sfoas.city as scity, sfoas.region as sregion, sfoas.postcode as szip, sfoas.telephone as stel, sfoas.country_id as scountry,

然后我加入了地址表两次

LEFT JOIN sales_flat_order_address sfoab
ON sfo.entity_id = sfoab.parent_id AND sfoab.address_type = 'billing'
LEFT JOIN sales_flat_order_address sfoas
ON sfo.entity_id = sfoas.parent_id AND sfoas.address_type = 'shipping'

然后最后在 while 循环我的变量中

$billing = ucfirst($row['billing']);
$billing_firstname = $row['bfirst'];
$billing_lastname = $row['blast'];
$billing_name = ucwords($billing_firstname . " " . $billing_lastname);
$billing_street = ucwords($row['bstreet']);
$billing_city = ucwords($row['bcity']);
$billing_region = $row['bregion'];
$billing_postcode = $row['bzip'];
$billing_telephone = $row['btel'];
$billing_country = $countries[$row['bcountry']];
$shipping = ucfirst($row['shipping']);
$shipping_firstname = $row['sfirst'];
$shipping_lastname = $row['slast'];
$shipping_name = ucwords($shipping_firstname . " " . $shipping_lastname);
$shipping_street = ucwords($row['sstreet']);
$shipping_city = ucwords($row['scity']);
$shipping_region = $row['sregion'];
$shipping_postcode = $row['szip'];
$shipping_telephone = $row['stel'];
$shipping_country = $countries[$row['scountry']];

其他人建议使用GROUP BY或DISTINCT。当我使用这些方法时,它不会同时显示账单和送货地址。它只会显示账单,而不显示送货地址。

当我关闭这些方法时,计费和运输都显示,但它会导致其他表中的其他字段输出两次。

所以我找到的唯一解决方案是加入地址表两次。这样做,我得到了我想要的。while 循环不会循环两次来获取两种地址类型。

如果您知道更好或更有效的方法来实现此目的,请告诉我。我是 MySQL 查询和 while 循环的新手。

您可以尝试按唯一列分组吗:像这样?

<?php 
    //THE ONLY ADDITION HERE IS THE "GROUP BY" CLAUSE
    //OTHERWISE THIS IS YOUR OWN CODE WITH THE EXCEPTION OF FORMATTING...

        $query_order = "
            SELECT
            sfo.entity_id,
            sfo.status,
            sfo.created_at,
            sfo.customer_firstname,
            sfo.customer_lastname,
            sfo.customer_email,
            sfo.subtotal,
            sfo.shipping_amount,
            sfo.tax_amount,
            sfo.grand_total,
            sfo.total_paid,
            sfo.total_due,
            sfo.total_item_count,
            sfoa.address_type,
            sfoa.firstname,
            sfoa.lastname,
            sfoa.street,
            sfoa.city,
            sfoa.region,
            sfoa.postcode,
            sfoa.telephone,
            sfoa.country_id,
            sfoi.product_id,
            sfoi.name,
            sfoi.sku,
            sfoi.qty_ordered,
            sfoi.price,
            sfoi.original_price,
            sfoi.row_total,
            sfoi.additional_data as additional_data1,
            sfst.track_number,
            sfst.carrier_code,
            sfst.title,
            sfop.additional_data as additional_data2,
            sfop.amount_paid,
            sfop.amount_ordered

            FROM sales_flat_order_address sfoa,
                 sales_flat_order sfo

            JOIN sales_flat_order_item sfoi
            ON sfo.entity_id = sfoi.order_id
            JOIN sales_flat_order_item sfoi
            ON sfo.entity_id = sfoi.order_id
            JOIN sales_flat_shipment_track sfst
            ON sfo.entity_id = sfst.order_id
            LEFT JOIN sales_flat_order_payment sfop
            ON sfo.entity_id = sfop.entity_id
            WHERE sfo.increment_id = " . (int)$po . "
            GROUP BY sfo.entity_id
            LIMIT 0 , 30";

根据你想要实现的目标;左加入可能会派上用场,如下所示:

$query_order = "
    SELECT
    sfo.entity_id,
    sfo.status,
    sfo.created_at,
    sfo.customer_firstname,
    sfo.customer_lastname,
    sfo.customer_email,
    sfo.subtotal,
    sfo.shipping_amount,
    sfo.tax_amount,
    sfo.grand_total,
    sfo.total_paid,
    sfo.total_due,
    sfo.total_item_count,
    sfoa.address_type,
    sfoa.firstname,
    sfoa.lastname,
    sfoa.street,
    sfoa.city,
    sfoa.region,
    sfoa.postcode,
    sfoa.telephone,
    sfoa.country_id,
    sfoi.product_id,
    sfoi.name,
    sfoi.sku,
    sfoi.qty_ordered,
    sfoi.price,
    sfoi.original_price,
    sfoi.row_total,
    sfoi.additional_data as additional_data1,
    sfst.track_number,
    sfst.carrier_code,
    sfst.title,
    sfop.additional_data as additional_data2,
    sfop.amount_paid,
    sfop.amount_ordered

    FROM sales_flat_order_address sfoa,
    sales_flat_order sfo                     

    LEFT JOIN sales_flat_order_item sfoi
    ON sfo.entity_id = sfoi.order_id
    LEFT JOIN sales_flat_shipment_track sfst
    ON sfo.entity_id = sfst.order_id
    LEFT JOIN sales_flat_order_payment sfop
    ON sfo.entity_id = sfop.entity_id
    WHERE sfo.increment_id = " . (int)$po . "
    GROUP BY sfo.entity_id
    LIMIT 0 , 30";

我希望这有所帮助...