I have a query which converts more than a row to single row. I wanted to know if there is any technique better than . To illustrate our case I have taken a simple usercars relation and simulated queries similar to our application.
table: Users PrimaryKey: UserId
---------------------------------------
| UserId | UserDetails1 | UserDetails2|
---------------------------------------
| 1 | name1 | Addr1 |
| 2 | name2 | Addr2 |
---------------------------------------
table: UserCars Unique Constraint(UserId, CarType)
index on userid, cartype
-------------------------------------------
| UserId | CarType | RedCount | BlueCount |
-------------------------------------------
| 1 | SUV | 1 | 0 |
| 1 | sedan | 1 | 2 |
| 2 | sedan | 1 | 0 |
-------------------------------------------
Consider CarType as an enum type with values SUV and sedan only
Application needs to fetch UserDetails1, sum(RedCount), sum(BlueCount), SUV's RedCount, SUV's BlueCount, sedan RedCount, sedan BlueCount for every user in a single query.
For the above example, the result should be like
--------------------------------------------------------------------------------
| UserId | UserDetails1 | TotalRed |TotalBlue|SUVRed|SUVBlue|sedanRed|sedanBlue|
--------------------------------------------------------------------------------
| 1 | name1 | 2 | 2 | 1 | 2 | 1 | 0 |
| 2 | name2 | 1 | 0 | 0 | 0 | 1 | 0 |
--------------------------------------------------------------------------------
Currently, our query is like below
SELECT
--User Information
u.UserId, u.UserDetails1,
--Total Counts by color
count_by_colour.TotalRed, count_by_colour.TotalBlue,
-- Counts by type
COALESCE(suv.red, 0) AS SUVRed, COALESCE(suv.blue, 0) AS SUVBlue,
COALESCE(sedan.red, 0) AS sedanRed, COALESCE(sedan.blue, 0) AS sedanBlue
FROM Users u
JOIN (
SELECT c.UserId, SUM(RedCount) as TotalRed,
SUM(BlueCount) AS TotalBlue
FROM UserCars c GROUP BY UserId
) count_by_colour
ON (u.UserId = count_by_colour.UserId)
LEFT JOIN (
SELECT UserId, RedCount AS red, BlueCount AS blue
FROM UserCars
WHERE CarType = 'SUV') suv
ON (u.UserId = suv.UserId)
LEFT JOIN (
SELECT UserId, RedCount AS red, BlueCount AS blue
FROM UserCars
WHERE CarType = 'sedan') sedan
ON (u.UserId = sedan.UserId)
Though the query fetches data as expected, I wanted to know if there is any technique better than this. In this example, I have given only two types (SUV and sedan) but in our original application which is related to marketing, has more types which means more left joins.
Note: tables cannot be altered as there are other applications use the same
Thanks,
Ravi
mysqlandpostgresql?