简体   繁体   中英

How do I do a mysql join and limit the number of identical results for the leftmost table to 1?

My query looks like this

SELECT DISTINCT
    addr.`Linje-ID` as lineid,
    addr.`Sluttbruker` as companyname,
    addr.`Gate` as street,
    addr.`Husnr` as housenr,
    addr.`Postnr` as zip,
    addr.`Poststed` as location,
    loc.`UX_KOORDINAT` as coord_x,
    loc.`UY_KOORDINAT` as coord_y,
    loc.`ADRESSE_ID` as addr_id

FROM
    addresses addr INNER JOIN
    locationdata loc ON
        loc.`POSTSTED` = addr.`Poststed` AND
        loc.`POST_NR` = addr.`Postnr` AND
        loc.`GATENAVN` = UPPER(addr.`Gate`) AND
        loc.`HUSNUMMER` = addr.`Husnr`

The goal is for the query to return EVERY result in "addresses" with matching data from "locationdata" for each one. This query does that, but it also duplicates the result from "addresses" for every additional match it finds in "locationdata".

How can I change my query to return only all the rows in "addresses" (`Linje-ID` is the unique identifier)

SELECT 
    addr.`Linje-ID` as lineid,
    addr.`Sluttbruker` as companyname,
    addr.`Gate` as street,
    addr.`Husnr` as housenr,
    addr.`Postnr` as zip,
    addr.`Poststed` as location,
    loc.`UX_KOORDINAT` as coord_x,
    loc.`UY_KOORDINAT` as coord_y,
    loc.`ADRESSE_ID` as addr_id

FROM
    addresses addr INNER JOIN
    locationdata loc ON
        loc.`POSTSTED` = addr.`Poststed` AND
        loc.`POST_NR` = addr.`Postnr` AND
        loc.`GATENAVN` = UPPER(addr.`Gate`) AND
        loc.`HUSNUMMER` = addr.`Husnr`
GROUP BY addr.`Linje-ID`

You need to decide what to do about multiple values being returned for a given addresses row by wrapping the columns from the locationdata table in aggregate functions. Here I assumed you simply wanted the minimum value:

Select addr.Linje-ID as lineid
    , addr.Sluttbruker As companyName
    , addr.Gate As street
    , addr.Husnr As housenr
    , addr.postnr As zip
    , addr. poststed As location
    , Min( loc.UX_KOORDINAT ) As coord_x
    , Min( loc.UY_KOORDINAT ) As coord_y
    , Min( loc.adresse_id ) As addr_id
From addresses As addr
    Join locationdata As loc
        On loc.poststed = addr.poststed
            And loc.post_nr = addr postnr
            And loc.gatnavn = upper(addr.gate)
            And loc.husnummer = addr.husnr
Group By addr.Linje-ID
    , addr.Sluttbruker
    , addr.Gate
    , addr.Husnr
    , addr.postnr
    , addr. poststed

Addition

Another solution, which would produce more logical results than above (although no more logical without more information) would be to arbitrarily choose a locationdata row for each address. To do that, we need to know the names of the Primary Key columns. Here I assumed they were called "PrimaryKeyColumn"

Select addr.Linje-ID as lineid
    , addr.Sluttbruker As companyName
    , addr.Gate As street
    , addr.Husnr As housenr
    , addr.postnr As zip
    , addr. poststed As location
    , loc.UX_KOORDINAT As coord_x
    , loc.UY_KOORDINAT As coord_y
    , loc.adresse_id As addr_id
From addresses As A
    Join    (
            Select addr.PrimaryKeyColumn
                    , Min( loc.PrimaryKeyColumn ) As locid
            From addresses As addr
                Join locationdata As loc
                    On loc.poststed = addr.poststed
                        And loc.post_nr = addr postnr
                        And loc.gatnavn = upper(addr.gate)
                        And loc.husnummer = addr.husnr
            Group By addr.PrimaryKeyColumn
            ) As Z
        On Z.PrimaryKeyColumn = addr.PrimaryKeyColumn
Join locationdata As loc
    On loc.PrimaryKeyColumn = Z.locid

ANSI-SQL compliant

SELECT
    addr.Linje-ID as lineid,
    addr.Sluttbruker as companyname,
    addr.Gate as street,
    addr.Husnr as housenr,
    addr.Postnr as zip,
    addr.Poststed as location,
    loc.UX_KOORDINAT as coord_x,
    loc.UY_KOORDINAT as coord_y,
    loc.ADRESSE_ID as addr_id
FROM (
    SELECT
        addr.Linje-ID as lineid,
        addr.Sluttbruker as companyname,
        addr.Gate as street,
        addr.Husnr as housenr,
        addr.Postnr as zip,
        addr.Poststed as location,
        (SELECT MIN(ADRESSE_ID) ADRESSE_ID
         FROM locationdata loc
         WHERE loc.POSTSTED = addr.Poststed AND
            loc.POST_NR = addr.Postnr AND
            loc.GATENAVN = UPPER(addr.Gate) AND
            loc.HUSNUMMER = addr.Husnr)
    FROM addresses addr
) ADDR
INNER JOIN locationdata loc ON loc.ADRESSE_ID = ADDR.ADRESSE_ID

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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