I'd like to ask you for help with a query (mysql). I have 3 tables:
1.table "reviews"
ID | content |
--------------------------------------
1 | content of first review
2 | content of second review
2.table "pros"
ID | reviews_ID | pros |
---------------------------------------
1 | 1 | good service |
2 | 1 | nice look |
3 | 1 | not bad price|
4 | 2 | good service |
5 | 2 | design |
3.table "cons"
ID | reviews_ID | pros |
---------------------------------------
1 | 1 | delays |
4 | 2 | mistakes |
5 | 2 | troubles |
What I am trying to do is merge informations from these 3 tables, where "reviews" table is the main one and table 2, 3 are pointing to it (reviews_ID).
I'd like to get results like this:
=> content of first review
+ good service - delays
+ nice look
+ not bad price
of course in array/result, this is just for better understand :)
try this sqlFiddle
with GROUP_CONCAT you can explode pros and cons into an array or whatever in php.
SELECT content,p.pros,c.cons
FROM reviews
LEFT JOIN
(SELECT reviews_id,GROUP_CONCAT(pros)as pros
FROM pros
GROUP BY reviews_id)as p
ON p.reviews_id = reviews.id
LEFT JOIN
(SELECT reviews_id,GROUP_CONCAT(cons)as cons
FROM cons
GROUP BY reviews_id)as c
ON c.reviews_id = reviews.id
WHERE reviews.id = 1;
result will be
CONTENT PROS CONS
content of first review good service,nice look,not bad service delays
SELECT statement produces only two-dimensional table. so, you could not obtain hierarchical tree using STANDARD SELECT. I suggest following SQL and convert display format in client side.
SELECT 'content',r.content as value
FROM reviews r
WHERE r.ID = 1
UNION
SELECT 'pros', p.pros
FROM reviews r LEFT JOIN pros p
ON r.ID = p.reviews_ID
WHERE r.ID = 1
UNION
SELECT 'cons', c.cons
FROM reviews r LEFT JOIN cons c
ON r.ID = c.reviews_ID
WHERE r.ID = 1
Try this:
SELECT A.content, B.pros, C.cons
FROM reviews A LEFT JOIN pros B ON A.ID = B.reviews_ID
LEFT JOIN cons C ON A.ID = C.reviews_ID
Related
I want to plan my trips publicly so other people can join me. So, I have set-up an PHP site.
I have this tables:
trips:
+----+---------+------------+------------+-------------------------+
| id | title | date_start | date_end | marker_adress |
+----+---------+------------+------------+-------------------------+
| 1 | Berlin | 2015-07-10 | 2015-07-11 | Potsdamer Platz, Berlin |
| 2 | Hamburg | 2015-07-16 | 2015-07-18 | Jungfernstieg, Hamburg |
+----+---------+------------+------------+-------------------------+
fellows:
+----+---------+---------------+
| id | trip_id | twittername |
+----+---------+---------------+
| 1 | 1 | prtyengopls |
| 2 | 1 | itobi_yt |
| 3 | 1 | jessisadancer |
| 4 | 2 | jessisadancer |
| 5 | 2 | woelfch3n |
+----+---------+---------------+
For displaying sake, I want to query them in one query. How can I query the database so I have something like this? (I know, it's JSON but it shows the structure very well.)
{
"id": 1,
"date_start": "2015-07-10",
"date_end": "2015-07-11",
"marker_adress": "Potsdamer Platz, Berlin",
"fellows": [
{
"id": 1,
"twittername": "prtyengopls"
},
{
"id": 2,
"twittername": "itobi_yt"
},
{
"id": 3,
"twittername": "jessisadancer"
}
]
}
First you have to use a LEFT JOIN like this:
SELECT
t.id AS tripID,
t.title AS title,
t.date_start AS dateStart,
t.date_end AS dateEnd,
t.marker_address AS markerAddress,
GROUP_CONCAT(DISTINCT CAST(f.id AS CHAR)) AS fellowID,
GROUP_CONCAT(DISTINCT CAST(f.twittername AS CHAR)) AS twitterName
FROM trips t LEFT JOIN fellows f ON t.id = f.trip_id
GROUP BY t.id
By using this you will get a single row for each trip and you can loop over fellowID and twitterName for each row, as it will be comma delimited list like this:
fellowID: 1,2,3
twitterName: prtyengopls,itobi_yt,jessisadancer
Edit 1: I got a new column to trips called checked which is a boolean.
Could you update your query, so only trips that have this boolean
toggled on are displayed?
SELECT
t.id AS tripID,
t.title AS title,
t.date_start AS dateStart,
t.date_end AS dateEnd,
t.marker_address AS markerAddress,
GROUP_CONCAT(DISTINCT CAST(f.id AS CHAR)) AS fellowID,
GROUP_CONCAT(DISTINCT CAST(f.twittername AS CHAR)) AS twitterName
FROM trips t INNER JOIN fellows f
ON t.id = f.trip_id AND t.checked = 1
GROUP BY t.id
I don't think it's possible like you expected in SQL. Just to answer your question and show you the problem: you have to use a join (left, inner or something ... depends of your database structure; I always prefer left joins if possible) to get all information in just one query:
SELECT * FROM trips t LEFT JOIN fellows f on t.id = f.trip_id WHERE t.id = 1;
But you always will get the trip information with every row, and for that you have to process it afterwards. You will never able to select such a nested structure, you will always get a flat one.
So I would recommend to split it into two queries like this:
SELECT * FROM trips WHERE id = 1;
SELECT * FROM fellows WHERE trip_id = 1;
You will have to process the information afterwards too, but you just select the wanted information from your database.
Hope that helps.
Im not very familiar with using 'join' in queries. I really tried solving this by my own, but it seems to be too hard.
I got 2 Tables:
Table 'users':
+-----------------+-----------------+
| member | online |
+-----------------+-----------------+
| mahran | 1 |
| peter | 1 |
| Jen | 1 |
| Steve | 0 |
+-----------------+-----------------+
Table 'tickets'
+-----------------+----------------+----------------+
| name | category | time |
+-----------------+----------------+----------------+
| mahran | silver | 1 |
| peter | blue | 1 |
| mahran | blue | 2 |
| peter | red | 3 |
| peter | green | 2 |
| Jen | silver | 1 |
+-----------------+----------------+----------------+
The chellange:
I need each member (users.member) who's online (users.online). The next thing is to get the category for each member (user.member = tickets.name) with the highest time (probably ORDER BY time DESC LIMIT 1).
So, for example:
Peter is online. Peters highest time is 3 at the position of category=red. So I want peter to show up in the result with his category 'red'. Mahran would show up with blue. Jen would get silver. And steve would be left out because he's not online.
I hope this was clear. In general I know how the queries would look like but theres no chance for me merging them together.
What needs to be merged:
SELECT member FROM users WHERE online = 1;
|
v for each member
SELECT category FROM tickets WHERE name=users.member ORDER BY time DESC.
So, any ideas how to solve this?
Here is a fiddle with a not working query: Click
You can do this easily with a correlated subquery:
select u.member,
(select t.category
from tickets t
where t.name = u.member
order by t.time desc
limit 1
) as MostRecentCategory
from users u
where u.online = 1;
This can make use of the following indexes: users(online, member) and ticket(member, time, category).
Here is the query you're looking for:
SELECT U.member
,T.category
FROM users U
INNER JOIN tickets T ON T.name = U.member
INNER JOIN (SELECT T2.name
,MAX(T2.time) AS [maxTime]
FROM tickets T2
GROUP BY T2.name) AS M ON M.name = T.name
AND M.maxTime = T.time
WHERE U.online = 1
The use of [name] to join the two tables is not a good practice, it's much better to use keys instead. But my query is just here to help you understanding the process of jointure.
Hope this will help you.
If i understand you correctly
SELECT DISTINCT users.member, tickets.category FROM tickets JOIN users ON users.member = tickets.name WHERE users.online = 1 ORDER BY tickets.time DESC
Can you make sql fiddle?
USE DISTINCT
stackoverflow.com/questions/11704012/mysql-distinct-join
try this
SELECT DISTINCT User.member,Ticket.category FROM users AS USER
INNER JOIN tickets AS Ticket ON (User.member = Ticket.name)
WHERE User.online = 1;
Sorry, but peter seems to be RED, It's time is 3. Don't you?
Depending on table definition, is not guaranteed to have one only result for each user.
For example, if peter has time 3 in two categories, you can get one different category depending of the SQL sorting method.
To be sure, tickets.Category and tickets.time must be in a unique key (both toghether, not a unike key for each field)
Assuming that, the Query could be this.
select t2.name, t2.category
from
tickets t2
INNER JOIN (Select
u.member, max(time)
from users u, tickets t
where
u.member = t.name
and u.online = 1
group by u.member
) as usermaxtime on t2.name = usermaxtime.member;
I'm making a search function in PHP and I have three tables that I wish to join to a single one; the three tables looks as follow:
band
ID | bands
---+----------
1 | Muse
2 | Coldplay
3 | etc.
release
ID | releases
---+----------
1 | Showbiz
2 | Origin of Symmentry
3 | etc.
track
ID | tracks
---+-----------
1 | Sunburn
2 | Muscle Museum
3 | etc.
I want these tables to be put into this:
discografic
ID | band_id | release_id | track_id
---+----------+-------------+---------
1 | 1 | 1 | 1
2 | 1 | 1 | 2
3 | etc.
So that the table with the SQL code looks like this:
discografic
ID | bands | releases | tracks
---+----------+-------------+---------
1 | Muse | Showbiz | Sunburn
2 | Muse | Showbiz | Muscle Museum
3 | etc.
I want to INNER JOIN these tables. I joined one but I can't really figure out how the get the last joined as well.
SELECT *
FROM band
INNER JOIN discografic
ON band.id = discografic.band_id
This should probably have its own question; I also want to be able to search this database, but only have the result show up once, and also reference to the band every time. For example, if I search "Showbiz" it will give me "Muse", and only show it once.
Note: This is for testing purposes only, security is none of my concerns.
Try with this query:
select d.id,b.bands,r.releases,t.tracks from discografic as d INNER JOIN band as b on
d.band_id=b.id INNER JOIN release as r on d.release_id=r.id INNER JOIN track as t on
d.track_id=t.id GROUP BY d.id
Try This query
Select a.ID,b.bands,c.releases,d.tracks from discografic as a
inner join band as b on a.band_id = b.ID
inner join release as c on a.release_id = c.ID
inner join track as d on a.track_id = d.ID
where b.bands = 'Muse'
Use this query to insert the data like you wanted:
Insert into discograpy
(id,bands,releases,tracks)
SELECT band.ID,bands,releases,tracks
FROM band
INNER JOIN releases
ON band.id = releases.id
inner join track
on band.id = track.id
Use this query to show you only one band:
Declare #releases varchar(50)
Set #releases = 'showbiz'
SElect distinct bands from discograpy where releases = #releases
Here any variable can be passed or set in place of showbiz. This is an example
I'm having a lot of difficulties in manipulating information in order to achieve the desired result. Through a query I join with the following result:
Area | ID_AT | AT | TYPE
-----------------------------------------
Informatica | 1 | Sistemaa | E
Informatica | 3 | engraçado | E
Informatica | 3 | engraçado | I
Gestão | 2 | aaaaa | I
query:
select a.Area, c.ID_AT, c.AT, dest.type
from AREA_AT a
left join AT_C c on a.id_AREA_AT = c.id_AREA_AT
left join dest_atv d on d.id_AT = c.id_at and d.id_uo = c.id_uo
left join CLIE dest on d.id_CLIE = dest.id_CLIE
where id.uo = 1222
order by a.id_AREA_AT, c.id_at, dest.type
But what I want is to create a table in php as follows:
Area | ID_AT | AT | E | I
-------------------------------------------
Informatica | 1 | Sistemaa | X |
Informatica | 3 | engraçado | X | X
Gestão | 2 | aaaaa | | X
In short, what I intend to do here is to show only one table ID ativ, showing that may exist or not type I or E depending on what comes from the query.
Do I have to modify the query to facilitate the work myself? Or will I have to create a fairly complicated algorithm in php to perform this function? Ando here turns hours and still could not find a solution that will can help me?
It sounds like you need to do a pivot query. Something like
select a.Area,
c.ID_AT,
c.AT,
max( case when dest.type = 'E' then 'X' else null end) E,
max( case when dest.type = 'I' then 'X' else null end) I
from AREA_AT a
left join AT_C c on a.id_AREA_AT = c.id_AREA_AT
left join dest_atv d on d.id_AT = c.id_at and d.id_uo = c.id_uo
left join CLIE dest on d.id_CLIE = dest.id_CLIE
where id.uo = 1222
group by a.area, c.id_at, c.at
order by a.area, c.id_at
Note that you won't be able to ORDER BY the a.id_area_at column if you are not selecting (and grouping by) that column in this formulation. I changed that to sort by a.area instead.
I actually have these tables :
- Table games -
ID
Name
- Table ean -
ID
ID_games
EAN
And I have this request :
SELECT games.*, ean.EAN
FROM games
LEFT JOIN ean ON (games.ID = ean.ID_games)
The result will be something like this :
| 1 | Half Life | 358958595 |
| 1 | Half Life | 589584859 |
| 2 | Half Life 2 | 385953684 |
| 2 | Half Life 2 | 585100335 |
etc.
When I do my request and use it in php, it is not useful to have a lot of line with about the same results. I would like to do something like this :
SELECT games.*, ConvertToArray(ean) AS ean_array
FROM games
LEFT JOIN ean ON (games.ID = ean.ID_games)
And have results like this :
| 1 | Half Life | (358958595,589584859) |
| 2 | Half Life 2 | (385953684,585100335 ) |
etc.
Is it possible to that with mysql ? Without an UDF ? And with an UDF ?
Thank you,
Kevin
Do you object to using GROUP_CONCAT? This would give you a nice delimited list (Assuming the ean value will never have your delimiter within):
SELECT games.*, GROUP_CONCAT(ean.EAN) AS ean_list,
FROM games
LEFT JOIN ean
ON games.ID = ean.ID_games
GROUP BY games.ID, games.name
Resulting in:
| 1 | Half Life | 358958595,589584859 |
| 2 | Half Life 2 | 385953684,585100335 |
Also, here's a qeustion I found with this logic applied: mySql - creating a join using a list of comma separated values
See GROUP_CONCAT().
Example can be found here.
Your query would look something like:
SELECT games.*, GROUP_CONCAT(DISTINCT ean) AS ean_array
FROM games
LEFT JOIN ean ON (games.ID = ean.ID_games)
GROUP BY games.ID
Try this one:
SELECT g.id, GROUP_CONCAT(CAST(e.ean AS CHAR) SEPARATOR ', ')
FROM games g
LEFT JOIN ean e ON g.id = e.id_games
GROUP BY g.id;