MySQL JOIN table problem and aggregation

I have three tables. This request will log the correct answer (x-lines for btv.id_user with corresponding btv.cas and race.id_zavod

SELECT `btv.id_user`, `btv.id_zavod`,`btv.cas`
FROM `btv`
JOIN `btu` ON `btv.id_user` = `btu.id_user`
JOIN `race` ON 'btv.id_zavod' = `race.id_zavod`
WHERE `race.type` = '8' AND `btv.id_user` = '607'

      

Result:

| 607 |  512 | 03:15:58 |  
| 607 |  730 | 03:01:18 |  
| 607 |  164 | 03:07:26 |  
| 607 |  767 | 02:58:31 |  
| 607 | 1147 | 03:06:47 |  
| 607 | 1149 | 03:09:41 |  
| 607 | 1178 | 03:24:20 | 

      

But when I try to concatenate it into one line using id_user it returns the correct min btv.cas value but enters incorrectly into the incorrect combination race.id_zavod

SELECT `btv.id_user`, `btv.id_zavod`, MIN( `btv.cas` )
FROM `btv`
JOIN `btu` ON `btv.id_user` = `btu.id_user`
JOIN `race` ON 'btv.id_zavod' = `race.id_zavod`
WHERE `race.type` = '8' AND `btv.id_user` = '607'
GROUP BY `btv.id_user`

      

Result:

| 607 | 512 | 02:58:31 |

      

+1


source to share


5 answers


When you use GROUP BY, the columns in the select list must satisfy one of the following:

  • Column named in GROUP BY (like btv.id_user

    in your example)
  • The column is inside an aggregate function (for example MIN( btv.cas )

    )
  • Column is the functional dependency of the column (s) that you named in GROUP BY.

This is a mistake in your request: btv.id_zavod

has many meanings for each value btv.id_user

. This does not satisfy functional dependency. For each value, there id_user

must be only one value in id_zavod

for it to be a functional dependency.

On some brands of databases, this query will actually give you an error. MySQL is more flexible by trusting you to only specify columns in the select list, which are functional dependencies of the columns (s) that you named in the GROUP BY.

Here's a query that returns what you want, the MIN value btv.cas

for id_user

, with the corresponding value btv.id_zavod

:



SELECT b1.id_user, b1.id_zavod, b1.cas
FROM btv AS b1
 JOIN btu ON (b1.id_user = btu.id_user)
 JOIN race ON (b1.id_zavod = race.id_zavod)
 LEFT OUTER JOIN btv AS b2 ON (b1.id_user = bt2.id_user AND 
   (b1.cas > b2.cas OR (b1.cas = b2.cas AND b1.primarykey > b2.primarykey))
WHERE race.type = '8' AND b1.id_user = '607'
 AND b2.id_user IS NULL;

      

In other words, you need to make your join as before, but then re-join it to btv

see if there is another row with the same value id_user

and less value in cas

. Use the BUILT-IN CONNECTION because you are looking for a case where there is no match. You can check this with b2.id_user IS NULL

, because OUTER JOIN makes all columns NULL when there is no match.

Note that there may be relationships, so we add an additional term using the primary key as a tiebreaker.

You don't need to use GROUP BY in this query. This is implicitly taken care of, because there will only be one row that satisfies the OUTER JOIN condition.

0


source


The request you wrote:

SELECT `btv.id_user`, `btv.id_zavod`, MIN( `btv.cas` )
FROM `btv`
JOIN `btu` ON `btv.id_user` = `btu.id_user`
JOIN `race` ON 'btv.id_zavod' = `race.id_zavod`
WHERE `race.type` = '8' AND `btv.id_user` = '607'
GROUP BY `btv.id_user`
      



will not work. You need the id_zavod group or something. Can you tell us which query you are actually using? And what result do you expect?

+1


source


Try:

SELECT `btv.id_user`, `btv.id_zavod`, MIN( `btv.cas` )
FROM `btv`
Inner JOIN `btu` ON `btv.id_user` = `btu.id_user`
Inner JOIN `race` ON 'btv.id_zavod' = `race.id_zavod`
WHERE `btv.id_user` = '607'
GROUP BY `btv.id_user` having `race.type` = '8'

      

0


source


I'm not sure what you are trying to accomplish, but you might be looking for GROUP_CONCAT to function? ?

0


source


Are you just trying to get the lowest btv.cas and other relevant columns? If so, you can simply order btv.cas and limit to 1 hit:

SELECT `btv.id_user`, `btv.id_zavod`,`btv.cas`
FROM `btv`
JOIN `btu` ON `btv.id_user` = `btu.id_user`
JOIN `race` ON 'btv.id_zavod' = `race.id_zavod`
WHERE `race.type` = '8' AND `btv.id_user` = '607'
ORDER BY `btv.cas` LIMIT 1
      

0


source







All Articles