Query tables from a list of ids - mysql

I'm looking for a way to query tables from a list of ID's in Mysql. I have a query that works in postgres and SQL Server that looks like this:
SELECT a.vehicle_id, a.make, a.model, b.id as people_id, b.name as owner
FROM (values (6,3),(7,3),(3,4),(4,2)) as jt (vehicle_id, people_id)
JOIN vehicles a ON (a.vehicle_id = jt.vehicle_id AND a.people_id = jt.people_id)
JOIN people b ON (b.id = v.people_id)
So I have an array of id's that are the same as vehicle_id and people_id.
I'm wondering if there's a way to do this in MySQL or if I need to convert the ID's and add them to a where clause? That could get pretty horrendous looking like this: WHERE (a.vehicle_id = 3 AND a.people_id = 4) OR (a.vehicle_id = 4 AND a.people_id = 2) OR … etc

Answer contributed by #Strawberry. This one does the trick nicely!
Assigning the ID's to fields in a where clause:
SELECT a.vehicle_id, a.make, a.model, b.id as people_id, b.name as owner
FROM vehicles a
JOIN people b ON (b.id = a.people_id)
WHERE (vehicle_id, people_id) IN ((6,3),(7,3),(3,4),(4,2))

Related

Query to insert a second table into the first table if table1.id = table2.table1_id

I have two tables.
*brands b*
id, name, img
*models m*
id, name, img, brand_1
I would like to get the following output:
Expected result / output
b.id,
b.name,
b.img,
models = m.id, m.name, m.img (where b.id = m.brand_id);
Do I have to do two steps for this?
give me all the brands
iterate brands and give me all models that are m.brand_id = b.id.
I hope you understand what I mean. In the PHP Laravel Framework you can get one to many relationships as a collection. Can I solve this with a query? And is my approach the right one at all?
You can laravel always let you show the raw query that the quera builder constructs.
but basically you are searching for an INNER JOIN
SELECT
b.id,
b.name,
b.img,
m.id as models
, m.name
, m.img
FROM models m INNER JOIN brands ON b.id = m.brand_id;

Multiple LEFT JOIN in SQL Running Slow. How do I optimize it?

I am combining three tables - persons, properties, totals - using LEFT JOIN. I find the following query to be really fast but it does not give me all rows from table-1 for which there is no corresponding data in table-2 or table-3. Basically, it gives me only rows where there is data in table-2 and table-3.
SELECT a.*, b.propery_address, c.person_asset_total
FROM persons AS a
LEFT JOIN properties AS b ON a.id = b.person_id
LEFT JOIN totals AS c ON a.id = c.person_id
WHERE a.city = 'New York' AND
c.description = 'Total Immovable'
Whereas the following query gives me the correct result by including all rows from table-1 irrespective of whether there is corresponding data or no data from table-2 and table-3. However, this query is taking a really long processing time.
FROM persons AS a
LEFT JOIN
properties AS b ON a.id = b.person_id
LEFT JOIN
(SELECT person_id, person_asset_total
FROM totals
WHERE description = 'Total Immovable'
) AS c ON a.id = c.person_id
WHERE a.city = 'New York'
Is there a better way to write a query that will give data equivalent to second query but with speed of execution equivalent to the first query?
Don't use a subquery:
SELECT p.*, pr.propery_address, t.person_asset_total
FROM persons p LEFT JOIN
properties pr
ON p.id = pr.person_id LEFT JOIN
totals t
ON a.id = c.person_id AND t.description = 'Total Immovable'
WHERE p.city = 'New York';
Your approach would be fine in almost any other database. However, MySQL materializes "derived tables", which makes them much harder to optimize. The above has the same effect.
You will also notice that I changed the table aliases to be abbreviations for the table names. This makes the query much easier to follow.

MySQL select from multiple tables using pivot

I have a many-to-many relationship between two tables, and I am using a pivot table to manage it.
The structure is as follows:
Table 1: cars (car_id, ...)
Table 2: brands (brand_id, ...)
Pivot table: cars_brands (car_id, brand_id, units, discount)
Using only one query, I am trying to select every field of the cars of a certain brand PLUS the number of units and discount (both fields of the pivot table...)
My try:
SELECT c.*, cb.units, cb.discount
FROM (cars c, cars_brands cb)
INNER JOIN cb ON c.car_id = cb.car_id
WHERE cb.brand_id = 1
ORDER BY c.car_id asc
I am getting a
#1066 - Not unique table/alias: 'cb'
MySQL error.
Any help is much appreciated.
Thanks in advance.
I think what you want is:
SELECT c.*, cb.units. cb.discount
FROM cars AS c
JOIN car_brands as cb ON cb.car_id = c.car_id
JOIN brands AS b ON b.brand_id = cb.brand_id
WHERE b.brand_name = 'Audi'
ORDER BY c.car_id ASC
you can try this also:-
select c.*,cb.units,cb.discount from car c,brands b,cars_brands cb where c.car_id=cb.car_id and b.brand_id=cb.brand_id and cb.brand_id=8888 order by cb.car_id asc;

My-Sql JOIN two tables error

I tried to combine two tables' data.
I got an error like this. can you see why?
Every derived table must have its own alias
SELECT a.title, number
FROM store a
JOIN
( SELECT count(b.code) as number
FROM redeem_codes b
WHERE product = a.title
AND available = "Available")
It's a little hard tell without knowing more about your table structures. I'll give a try anyway:
SELECT a.title, count(b.code) AS number FROM store a
LEFT JOIN redeem_codes b ON b.product = a.title
WHERE b.available = "Available"
GROUP BY a.title;
you need to have ALIAS on your subquery.
SELECT a.title, number 
FROM store a  
JOIN (subquery) b -- b is the `ALIAS`
-- and this query will not give you the result you want
but here's a more efficient query without using subquery,
SELECT a.title, count(b.code) number
FROM store a
INNER JOIN redeem_codes b -- or use LEFT JOIN to show 0
-- for those who have no product
ON b.product = a.title
WHERE b.available = 'Available'
GROUP BY a.title

MySQL "Distinct" join super slow

I have the following query which gives me the right results. But it's super slow.
What makes it slow is the
AND a.id IN (SELECT id FROM st_address GROUP BY element_id)
part. The query should show from which countries we get how many orders.
A person can have multiple addresses, but in this case, we only only want one.
Cause otherwise it will count the order multiple times. Maybe there is a better way to achieve this? A distinct join on the person or something?
SELECT cou.title_en, COUNT(co.id), SUM(co.price) AS amount
FROM customer_order co
JOIN st_person p ON (co.person_id = p.id)
JOIN st_address a ON (co.person_id = a.element_id AND a.element_type_id = 1)
JOIN st_country cou ON (a.country_id = cou.id)
WHERE order_status_id != 7 AND a.id IN (SELECT id FROM st_address GROUP BY element_id)
GROUP BY cou.id
Have you tried to replace the IN with an EXISTS?
AND EXISTS (SELECT 1 FROM st_address b WHERE a.id = b.id)
The EXISTS part should stop the subquery as soon as the first row matching the condition is found. I have read conflicting comments on if this is actually happening though so you might throw a limit 1 in there to see if you get any gain.
I found a faster solution. The trick is a join with a sub query:
JOIN (SELECT element_id, country_id, id FROM st_address WHERE element_type_id = 1 GROUP BY
This is the complete query:
SELECT cou.title_en, COUNT(o.id), SUM(o.price) AS amount
FROM customer_order o
JOIN (SELECT element_id, country_id, id FROM st_address WHERE element_type_id = 1 GROUP BY element_id) AS a ON (o.person_id = a.element_id)
JOIN st_country cou ON (a.country_id = cou.id)
WHERE o.order_status_id != 7
GROUP BY cou.id