I have this sql to query from different tables
SELECT *
FROM `person`
LEFT JOIN person_address
ON person_address.person_id=person.person_id
LEFT JOIN address_type
ON address_type.address_type_id=person_address.address_type_id
it return this data,
It's really tedious to achieve this json format
//json
[{
"person_id":"1",
"full_name":"john",
"scores": [{
"address_type":"billing",
"address_name":"Spain"
},{
"address_type":"home",
"address_name":"USA"
}]
}]
I should fix my sql query or it's that tedious I have to do manual looping using PHP to produce the json?
Tried DISTINCT
https://i.imgur.com/tZFvKAD.png
doesn't seems to work
here is a supper simplified version of what I am talking about.
Given this schema ( simple Many To Many )
CREATE TABLE a(
id INT(10)
);
INSERT INTO a (id)VALUES(1);
INSERT INTO a (id)VALUES(2);
CREATE TABLE b(
a_id INT(10),
c_id INT(10)
);
INSERT INTO b (a_id,c_id)VALUES(1,1);
INSERT INTO b (a_id,c_id)VALUES(1,2);
INSERT INTO b (a_id,c_id)VALUES(2,1);
INSERT INTO b (a_id,c_id)VALUES(2,2);
CREATE TABLE c(
id INT(10),
val VARCHAR(255)
);
INSERT INTO c (id,val)VALUES(1,'one');
Now if you run this query:
SELECT
c.val AS c_val
FROM
a
JOIN b ON a.id = b.a_id
JOIN c ON b.c_id = c.id
WHERE
c.id = 1;
You will get this result
'one'
'one'
But if you run this query
SELECT
b.a_id,
b.c_id,
c.val AS c_val
FROM
a
JOIN b ON a.id = b.a_id
JOIN c ON b.c_id = c.id;
Which is just display all you will see this
a_id | c_id | c_val
1 | 1 | one
2 | 1 | one
AS seen in this DB fiddle
https://www.db-fiddle.com/f/fZnRCSXeu3wYVFzn4NBjC5/0
This is pretty clear why in this simple example, but in a more complicated case it may not be as clear. This is especially true if the where clause matches multiple rows in the last table.
Besides that you should have the key in the bridge table ( b in the above example ) set as a compound primary key on the id's from the other 2 tables.
Now the way to fix the first query is to simply add DISTINCT to it
SELECT DISTINCT
c.val AS c_val
FROM
a
JOIN b ON a.id = b.a_id
JOIN c ON b.c_id = c.id
WHERE
c.id = 1;
Now the output is
'one'
AS seen in the last query in this updated fiddle
https://www.db-fiddle.com/f/fZnRCSXeu3wYVFzn4NBjC5/1
Related
I have to get A.Ref_id, B.Ref_id and B_Id's Ref_id
Table A_B having Column_A_ID and Column_B_ID
Table A having ID, Ref_id, Name, B_Id (This is the B.ID from table B)
Table B having ID, Ref_id, Name
Currently I'm having the following query
SELECT A.Ref_id as A_Ref_Id, B.Ref_id as B_Ref_Id, B_Id
FROM A_B
JOIN A on A_B.Column_A_ID = A.Id
JOIN B on A_B.Column_B_ID = B.Id
JOIN B AS Main_B on B.id = A.B_id;
By this query I'm getting the A.Ref_Id and B.Ref_Id columns correctly as they are showing their relevant Ref_id but for B_Id I want to have the Ref_id and it is showing the B.id instead.
You want this (right?): The value of B.Ref_id in the row where B.ID = A.B_Id while this row in turn must have A.ID=A_B.Column_A_ID. And the whole thing for every row in A_B:
SELECT A.Ref_id as A_Ref_id, B.Ref_id as B_Ref_id, Main_B.Ref_id
FROM A_B
JOIN A ON A_B.Column_A_ID = A.Id
JOIN B ON A_B.Column_B_ID = B.Id
JOIN B AS Main_B on Main_B.id = A.B_id;
(Last line of code with the important correction which was proposed by #Mojtaba)
So far, I see the ON condition of the last join has to use the alias name of table B:
SELECT A.Ref_id as A_Ref_Id, B.Ref_id as B_Ref_Id, B_Id
FROM A_B
JOIN A on A_B.Column_A_ID = A.Id
JOIN B on A_B.Column_B_ID = B.Id
JOIN B AS Main_B on Main_B.id = A.B_id;
By the way, having some example in sqlFiddle could be more helpful
I have two mysql tables called room_type and resve_room.
The room_type table has room numbers 5, 3, 6 ,9 ,10. The resve_room table has room numbers 3 and 9.
How can I write an SQL query that filters out reserved room number 3 and 9 from the room_type table. I want to return the following room numbers 5,6,10.
I have tried using the following SQL but it only returned 3 and 9 :
SELECT room_type.room_no
FROM room_type,in_hand_room
WHERE in_hand_room.room_no=room_type.room_no
&& room_type.room_id='$room_id
Try something like this
SELECT B.Accountid
FROM TableB AS B
LEFT
JOIN TableA AS A
ON A.ID = B.Accountid
AND A.ID IS NULL;
Or maybe this
select ids from TableB EXCEPT select id from TableA
Try the follwoing
SELECT room_type.room_no
FROM room_type
WHERE room_type.room_no NOT IN (SELECT resve_room.room_no from resve_room )
or in_hand_room instead of resve_room beacuse it 's not clear from your desc which one is your reservation table
I have two database tables with "one to many" relationship
let say, table A and Table B
One field from Table A is a foreign key in table B
I wanna fetch just one record from table A as well as table B (given table A's primary key)
table A
id name
--------------------
1 ABC
2 XYZ
Table B
id A_id email
------------------------------------------------
1 1 temp#temp1.com
2 1 temp#temp2.com
3 1 temp#temp3.com
4 2 temp#temp4.com
4 2 temp#temp5.com
Answer should be like this (Single Record From Table B)
For a.id = 1
A.id, A.name,B.email
-------------------------
1, ABC, temp#temp1.com
For a.id = 2
A.id, A.name,B.email
-------------------------
1, XYZ, temp#temp4.com
I used this query, but it returns all the records from table B(as table B has multiple records for each record in Table A)
SELECT a.id,a.name, b.email FROM A a, B b WHERE a.id = 1 AND b.A_id = a.id
I have created a SQL Fiddle for the demo here: http://www.sqlfiddle.com/#!2/15ae7/5
The query that you can use for getting the desired output is:
SELECT
tableA.id,
tableA.name,
tableB.email
FROM tableA
LEFT OUTER JOIN tableB ON tableB.A_id = tableA.id
GROUP BY tableB.A_id;
For more information on JOINS and GROUP BY you can refer to the following pages:
http://dev.mysql.com/doc/refman/5.0/en/join.html
https://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html
Try a JOIN
SELECT
a.id,
a.name,
b.email
FROM A a
LEFT JOIN B b ON b.A_id = a.id
WHERE a.id = 1;
GROUP BY b.A_id
More info on JOINS
You can use LIMIT if you want only one record.
SELECT a.id,a.name, b.email FROM A a, B b WHERE a.id = 1 AND b.A_id = a.id LIMIT 0,1
Hope this helps you.
I have the following table structures.
Table A
id name
1 name1
2 name2
Table B
a_id b_id
1 1
1 2
How can I select all rows of table A that have both a b_id of 1 and 2? Table B is a mapping table between table A and another table, whose contents do not matter for this question.
Thank you for your time and help!
This query uses COUNT(DISTINCT) to ensure the presence of both values. If I did not use DISTINCT it may incorrectly count rows in TableB that look like this as a match when it shouldn't:
a_id b_id
1 1
1 1
select a.id, a.name
from TableA a
inner join (
select a_id
from TableB
where b_id in (1, 2)
group by a_id
having count(distinct b_id) = 2 #this number matches no. of unique values in IN clause
) b on a.id = b.a_id
SQL Fiddle example
Correctness can be tricky on a question like this because your sample data is missing a key cases. Duplicate values for B_ID and the possibility that it can contain one of the ids but not both
e.g.
| A_ID | B_ID |
---------------
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 2 | 1 |
The best approach is to use Having (Distinct Count) = # of ids (RedFilter's) since its easy to add more ID's
The two other options are to use or multiple EXISTS or IN clauses (NickB's) or to join and filter multiple times (below) but can become tortuously long if you need to add additional ids.
SELECT DISTINCT a.id,
a.name
FROM TableA a
INNER JOIN TableB b1
ON a.id = b1.a_id
and b1.b_id = 1
INNER JOIN TableB b2
ON a.id = b2.a_id
and b2.b_id = 2
DEMO
SELECT * FROM A JOIN B ON A.id=B.a_id WHERE B.b_id IN(1,2);
Here's what I could come up with, it uses one subquery.
SELECT * FROM table_a a1
JOIN table_b b1
ON a1.id = b1.a_id
WHERE b1.b_id = 1 AND
EXISTS(
SELECT b2.b_id
FROM table_b b2
WHERE a1.id = b2.a_id
AND b2.b_id = 2
)
Didn't know SQL Fiddle exists, but here is one showing it working!
I'll take a stab at this too, with a self join:
SELECT A.* FROM B B1
JOIN B B2 ON B2.a_id = B1.a_id
JOIN A ON A.id = B1.a_id
WHERE B1.b_id = 1 AND B2.b_id = 2
I tested this, and it works. If (B.a_id, B.b_id) isn't unique, then you'll need DISTINCT to avoid duplicates.
SELECT TableA.* FROM TableA WHERE TableA.id IN(
SELECT TableB.a_id FROM TableB WHERE TableB.b_id IN(1,2))
I have two mysql tables. One table with strings, for example abc, def, ghi, jkl. The other table contains info about the strings in the other table, for example 'Three first letters in the alphabet', '3-6 letters in the alphabet', and so on. There can be multiple (around 25 rows) for each string in this table.
I want to return 3 rows from the second table for each string in the first one, for example:
table1.string | table2.info
---------------------------
abc | blahblah
abc | blahblah2
def | blahblah
abc | blahblah3
def | blahblah2
def | blahblah3
I can get the strings from table1 first, the do a foreach and execute even more queries to get limit 3 from the table2. But that does not seem to be good for the performance.
How would a query like this look like?
I don't know whether it works in MySQL, but in MSSQL this would be
SELECT
table1.string,
table2.info
FROM table1 INNER JOIN table2 ON table2.stringID = table1.ID
WHERE ROW_NUMBER() OVER (PARTITION BY table1.string ORDER BY table2.info) <= 3
You can try this (it's not very fast though):
SELECT string,info FROM
(
select t1.string, t2.info,
#n_rec := IF(#tmp!=t1.string,1,#n_rec+1) as nrec,
#tmp := t1.string
FROM
table_1 t1
INNER JOIN table_2 t2 ON t2.table_1_id = t1.id
order by t1.string
)yy
INNER JOIN (SELECT #n_rec := 0) X
INNER JOIN (SELECT #tmp:= null)Y
WHERE nrec <=3;
You might want to use LEFT JOIN table_2 instead of INNER JOIN table_2 if you need to include records from table_1 with no info in table_2.