简体   繁体   中英

Which column is printed when grouping by finds multiple rows with same value?

在此处输入图片说明

So my question is, if i group by ContacType on this resultset i will get 3 rows, one for TMV, one for TEL and another for EML, but if i print the ContactValue column which one will be printed for TMV and TEL? Is it the first occurrence for each one?342222 and 33333?Or is there an specific order when Grouping ?

In order for the query you are describing to be valid ANSI SQL, you would have to specify an aggregate function to be used against the ContactValue column. For example, if you wanted the alphabetically earliest contact value for each type, you could write:

SELECT
    ContactType,
    MIN(ContactValue) AS ContactValueFirst
FROM yourTable
GROUP BY
    ContactType;

MySQL happens to be unique in that it has a server mode called ONLY_FULL_GROUP_BY which, when disabled, would actually allow the following query:

SELECT
    ContactType,
    ContactValue
FROM yourTable
GROUP BY
    ContactType;

Your actual question may be which contact value would get returned in this case. Best practice is to not even rely on this server mode loophole, but rather to always use a query along the lines of the first one which I gave. One main reason for this is that if you write your code assuming ONLY_FULL_GROUP_BY mode is disabled, if that mode is ever enabled, your existing code could break.

From the documentation for ONLY_FULL_GROUP_BY mode:

If ONLY_FULL_GROUP_BY is disabled ... the server is free to choose any value from each group, so unless they are the same, the values chosen are nondeterministic , which is probably not what you want. Furthermore, the selection of values from each group cannot be influenced by adding an ORDER BY clause.

You should not run queries that produce nondeterministic results. If you do, you risk creating bugs in your code.

In practice, the current versions of MySQL return the first value read in index order when you execute a query like the one you show. The value returned depends on the index the query uses. This can change, depending on which indexes you add or drop from your table, or it can change depending on the optimizer's choice of which index to read.

Future versions of MySQL might change the implementation. They are under no obligation to preserve non-standard behavior. So if you try to depend on this "feature," you will get a surprise if you ever upgrade your version of MySQL. It could lead to bugs in your application that are hard to detect.

Also, different SQL database implementations might behave a different way. For example, SQLite is the only other database I know that allows these kinds of ambiguous queries, but SQLite returns the last value read in index order. Why? Just because of the way they implemented it. It's non-standard and arbitrary behavior anyway, so it can't be called wrong.

This is why it's a bad idea to create queries that have such variable results. It can lead to confusing application behavior.

In all other popular SQL databases (PostgreSQL, Oracle, Microsoft, etc.), it's simply an error to run such queries.

It's also an error in the ANSI SQL specification. When ONLY_FULL_GROUP_BY is disabled, MySQL allows usage that is not valid SQL. You should try to avoid it.


Re your comment on Tim's answer:

The idea here is, Entity BBB will have priority, so grouping by ContactType i would first want all contacts of BBB entity, now in this case only AAA has an email(EML) so i know that would return normally. The issue is that you have phone(TEL) and mobile (TMV) in both entities(BBB and AAA) but i would need the BBB ones in this case. That's i first ordered by BBB first and AAA second, thinking that Group By would return first occurrence of the ContactValue associated with the group by column (ContactType).

This sounds like it should be solved with a window function, not GROUP BY. You'll have to use MySQL 8.0 or later for this.

WITH OrderedContacts AS (
  SELECT Entity, ContactType, ContactValue,
    ROW_NUMBER() OVER (PARTITION BY ContactType ORDER BY Entity DESC) AS rownum
  FROM Contacts
)
SELECT * FROM OrderedContacts WHERE rownum = 1

The ORDER BY Entity DESC puts BBB first, if one exists for a given contact type. Then AAA follows. So if there is a BBB, it gets row number 1. If there is no BBB, then AAA gets row number 1. This way only one row per contact type is returned, and BBB naturally takes "priority".

If you use min or max for contact value then it will return min or max value for that contact type.If you want to do order by contacttype ordering .just write order by clause for it

Example : In this wil order by contacttype in ascending order

SELECT ContactType, MIN(ContactValue) AS ContactValueFirst FROM yourTable GROUP BY ContactType Order by 1

Output:

Contacttype Contactvalue EML China@port.com TEL 914444444 TMV. 312222

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