How to list data from join table in one row? - mysql

There 3 entities: 1) Question, 2) Tag and join table between them - question_has_tag.
When I make a select query like:
select * from question_has_tag as qht where qht.question_id = 6;
I'm getting the following result:
question_id| tag_id
6 | 1
6 | 2
6 | 3
and I needed to get:
question_id| tag_id
6 | 1, 2, 3
How to get it ?

You need to GROUP them and use GROUP_CONCAT
Like
SELECT question_id,GROUP_CONCAT(tag_id ORDER BY tag_id )
FROM question_has_tag as qht
WHERE qht.question_id = 6
GROUP BY question_id;

You're looking for the group_concat() function. This function aggregates a particular field, separating them with a arbitrary character(s).
select
question_id
, group_concat(
distinct tag_id
order by tag_id
separator ','
) as tag_id
from
question_has_tags
where
question_id = 6;

Related

How to group duplicated rows and count them?

my table:
id | item_id
1 | 5
2 | 5
3 | 7
4 | 2
sql:
$countWeek = $conn->query("SELECT count(item_id) FROM `myTable` GROUP BY `item_id`")->fetchColumn();
As you can see i have 2 duplicated rows with item_id = 5 i want to group these duplicated rows and output 3 rows on the count, but when i do echo $countWeek it output 1, why?
When i change the above sql to:
$countWeek = $conn->query("SELECT item_id FROM `myTable` GROUP BY `item_id`")->rowCount();
It returns the correct value, but i don't want to use rowCount() because i only need to count the rows and fetchColumn() with count() is far better in terms of speed.
You could use counct(distinct item_id)
SELECT count(distinct item_id)
FROM `myTable`

selecting multiple max values

i have a table like this on a mysql database:
id | item
-----------
1 | 2
2 | 2
3 | 4
4 | 5
5 | 8
6 | 8
7 | 8
i want the result to be 3 record with the highest Item value
select max(item) returns only 1 value
how can i select multiple max values?
thank you
You can use a derived table to get the maximum value and join it back to the original table to see all rows corresponding to it.
select t.id, t.item
from tablename t
join (select max(item) as mxitem from tablename) x
on x.mxitem = t.item
Edit:
select t.co_travelers_id, t.booking_id, t.accounts_id
from a_co_travelers t
join (select accounts_id, max(booking_id) as mxitem
from a_co_travelers
group by accounts_id) x
on x.mxitem = t.booking_id and t.accounts_id = x.accounts_id
If you use an 'aggregate function' without GROUP BY only one row will be returned.
You may use GROUP BY , with aggregate functions.
Here is SQLFiddle Demo
SELECT id,max(item) AS item
FROM table_name
GROUP BY id
ORDER BY item DESC
LIMIT 3
Hope this helps.
There is the graphical explanation.
There is script mysql (low abstraction level, no inner join or sth)
select * from ocena, uczen where ocena.ocena = (SELECT MAX(ocena.ocena) FROM ocena WHERE ocena.przedmiot_id="4" and ocena.uczen_id="1") and ocena.uczen_id=uczen.id and ocena.przedmiot_id="4" and uczen_id="1"

SQL Joint 2 table without duplicate rows

I`m trying to combine 2 tables without duplicate rows
Table 1 - modx_site_content
|id|pagetitle|introtext|pub_date|
---------------------------------
|3635| name1 |texttextt|17.02.2015
|3636| name1 |texttextt|18.02.2015
Table 2 - modx_site_tmplvar_contentvalues
|contentid|tmplvarid|value|
---------------------------
| 3635 | 1 |value1
| 3635 | 1 |value2
| 3636 | 1 |value3
I`m try to make all
|id|title|introtext|publishdate|photo|
--------------------------------------
|3635|name1|texttextt|17.02.2015|value1, value2
|3636|name1|texttextt|18.02.2015|value3
But the current result shows dublicate rows id 3535
|id|title|introtext|publishdate|photo|
--------------------------------------
|3635|name1|texttextt|17.02.2015|value1
|3635|name1|texttextt|17.02.2015|value2
|3636|name1|texttextt|18.02.2015|value3
My current sql resuest is
SELECT
modx_site_content.id,
pagetitle as 'title',
introtext,
pub_date as 'publishdate',
modx_site_tmplvar_contentvalues.value as 'photo'
FROM `modx_site_content`,
`modx_site_tmplvar_contentvalues`
WHERE parent IN (1153,3271)
AND pub_date>0
AND `contentid`= modx_site_content.id
AND `tmplvarid` IN (10, 15, 19)
Order by `pub_date` DESC LIMIT 20
The solution to your immediate problem is group by and group_concat():
SELECT c.id, c.pagetitle as title, c.introtext, c.pub_date as publishdate,
group_concat(cv.value) as sphotos
FROM `modx_site_content` c JOIN
`modx_site_tmplvar_contentvalues` cv
ON cv.`contentid`= c.id
WHERE c.parent IN (1153, 3271) AND c.pub_date > 0 AND
`tmplvarid` IN (10, 15, 19)
GROUP BY c.id, c.pagetitle, c.introtext, c.pub_date
Order by c.`pub_date` DESC
LIMIT 20;
I would also recommend:
Use explicit join syntax.
Define table aliases in the from clause.
Use table aliases for column references.
Don't use single quotes to define column aliases. You don't need an escape character for yours, so don't both using one.
MySQL has group_concat that may work (depending on data type):
SELECT
modx_site_content.id,
pagetitle as 'title',
introtext,
pub_date as 'publishdate',
group_concat(modx_site_tmplvar_contentvalues.value) as 'photo'
FROM `modx_site_content` JOIN
`modx_site_tmplvar_contentvalues` ON `contentid`= modx_site_content.id
WHERE parent IN (1153,3271)
AND pub_date>0
AND `tmplvarid` IN (10, 15, 19)
GROUP BY modx_site_content.id, pagetitle , introtext, pub_date

MySQL how to count from GROUP BY

date | userid | companyid
12.8.14 | 1 | 1
12.8.14 | 2 | 2
12.8.14 | 3 | 1
I had a table like above. It is easy to count how many company 1 from table with normal query.
My question is : if my query is select * from table where companyid = '1' group by date, how can i get mysql_num_row equal to 2 for company 1 and userid is 1 and 3?
select * from table where companyid = '1' group by date will only return me
mysql_num_row equal 1 and result 12.8.14 | 1 | 1
You can nest a query to get the sum of company one entries and then join that nested query to an outer query:
SELECT ABB2.*, ABB1.mysql_num_row
FROM `table` AS ABB2
JOIN
(SELECT companyid, COUNT(userid) AS mysql_num_row
FROM `table`
GROUP BY companyid) AS ABB1 ON ABB1.companyid = ABB2.companyid
WHERE ABB2.companyid = 1;
Example
try like this also
select *,(select count(*) from table1 where companyid=a.companyid) as count
from t as a where companyid=1
You wanted:
select date,companyid,count(*)
from table
where userid = 1
group by date,companyid

MYSQL select from table where field is in the field

UPDATED
id | id_list
1 | 2,3,5,7
2 | 1,4,5,6
3 | 1,4,6,7
4 | 2,3,5,8
5 | 1,2,4,8
6 | 2,3,7,8
7 | 1,3,6,9
8 | 4,5,6,9
9 | 7,8
let's say I'm up to the content of id=1
I wanted to select all the rows where id is in id_list of id=1 PLUS the row where id=1
so the result would be
rows with id = 1,2,3,5,7
How to do this query guys?
You can also use a self join
Using IN()
select * from atable a
join atable b on (a.id = b.id )
where 1 IN (a.id_list) or b.id =1
Fiddle with IN()
Using FIND_IN_SET()
select * from atable a
join atable b on (a.id = b.id )
where FIND_IN_SET('1', a.id_list) or b.id =1
Fiddle with FIND_IN_SET()
Using UNION ALL
select * from atable
where id =1
UNION ALL
select * from atable
where 1 IN (id_list)
Fiddle with UNION ALL
Your database design is broken; id_list should be represented as a join table instead of as a string. However, to solve your immediate problem:
select * from table where id=1
or id_list like '1%'
or id_list like '%,1,%'
or id_list like '%,1'
Adjust as needed for PreparedStatement. You have to provide all three cases because if you just did
or id_list like '%1%'
and id_list contained the value 11, you'd get an incorrect match
Try this (see SQL-Fiddle):
SELECT * FROM tbl
WHERE id = 1
OR INSTR((SELECT id_list FROM tbl WHERE id = '1'), id) > 0;
Tested with MySQL 5.5.30
try this one
select *
from tbl
where id=1
or id_list like '%1%'
This appears to call for a union of two sets. The one set would be the single row whose id matches the specified value:
SELECT
id
FROM
atable
WHERE
id = #id
The other set would be the result of this self-join:
SELECT
item.id
FROM
atable AS item
INNER JOIN
atable AS list
ON
FIND_IN_SET(item.id, list.id_list)
WHERE
list.id = #id
That is, the row with the specified id is matched against every row in the table on the condition that the other row's id is found in the specified row's id_list.
You can try the complete query at SQL Fiddle.
Please note that lists aren't a very good design feature. In your situation, it might be better to use a many-to-many table as suggested by #Othman. Only I would probably use a slightly different query to get the desired output, because his doesn't include the specified row itself:
SELECT
id
FROM
manytomany
WHERE
id = #id
UNION
SELECT
linked_id
FROM
manytomany
WHERE
id = #id
;
While the entries in manytomany are assumed to be unique, the query uses the UNION DISTINCT operator because of the potential duplicates returned by the first subquery, although it is possible to move the application of DISTINCT to the first subquery only like this:
SELECT DISTINCT
id
FROM
manytomany
WHERE
id = #id
UNION ALL
SELECT
linked_id
FROM
manytomany
WHERE
id = #id
;
That first subquery could actually be rewritten simply as SELECT #id AS id, but the rewrite would only make sense if the passed value was guaranteed to be valid, i.e. that it would definitely be found in manytomany.id.
Here's a demo for the other approach too (all three variations, including the SELECT #id AS id one).
I don't have an answer for your question but I encourage you to redesign your table like this I think this called many to many relation
id | friend
1 | 2
1 | 3
1 | 5
1 | 7
2 | 1
2 | 4
2 | 5
2 | 6
3 | 1
3 | 4
3 | 6
3 | 7
And then your query will be like this
SELECT DISTINCT(friend) FROM `new` WHERE id = 1
I am assuming you are using php..
My suggestion is to grab the id_list for id 1.
Explode that id_list on the comma, and then do another mysql query to grab the remaining results for 5|3|6|8
ex) $idarray = explode(",", $result);
select * from your_table where id in ('5','3','6','8')
OPTION 2:
SELECT * FROM your_table
WHERE id = '1'
OR id IN ('\''+(SELECT REPLACE(id_list,',','\',\'') FROM your_table WHERE id = '1')+'\'')
EDIT: Oops, sorry, that should be an OR instead.