GROUP_CONCAT issue with string - mysql

SELECT (SELECT GROUP_CONCAT(companyName)FROM company WHERE id IN (27,38)) AS companyName, t.*
FROM Test t
it return output like this,
>Apple, Sony
But if I pass the id as full string,
SELECT (SELECT GROUP_CONCAT(companyName)
FROM company WHERE id IN ("27,38")) AS companyName, t.*
FROM Test t
So it return first company name only, so output like this
>Apple
I want to retrieve the data like this Apple, Sony.(Like first query), How can I achieve this one?
Sample Table Structure below
company Table
--------------------
ID companyName
-------------------
27 Apple
28 Sony
. .
. .

You are passing 27 and 28 as single string so MySQL consider the first number which is 27, that's why it's returning apple. If you want return Apple and Sony you have to split the string.

You need to use
SELECT group_concat(companyName separator ',')
FROM company WHERE id IN ("27,38");

I saw your comments it looks like you are storing company ids for Trailers as a comma separated string which is against of normalization, Instead you can add new junction table which hold the reference of both tables company and trailers like
trailer
=======
id name
1 some name
company
id name
-------------------
1 Apple
2 Sony
trailer_companies (junction table)
trailer_id company_id
---------------------
1 27
1 38
Now you can query records by using joins
select t.*,group_concat(c.name) companyName
from trailer t
join trailer_companies tc on (t.id = tc.trailer_id)
join company c on (tc.company_id = c.id)
group by t.id
DEMO
If you want to continue with your current design which is strongly not advisable because it will be hard to optimize and not fit for scaled apps
SELECT
(SELECT
GROUP_CONCAT(companyName SEPARATOR ',')
FROM company
WHERE FIND_IN_SET(id,t.companyIds) > 0
) AS companyName, t.*
FROM Trailers t

Related

Select From table name obtained dynamically from the query

I have 3 Tables
campaign1 (TABLE)
id campaign_details
1 'some detail'
campaign2 (TABLE)
id campaign_details
1 'some other detail'
campaign_list (TABLE)
id campaign_table_name
1 'campaign1'
2 'campaign2'
Campaign list table contains the table name of the two tables described above. I want to Select from the Campaign List table and get the record count using the table name i get from this select
For eg.
using select i get campaign1(Table name). Then i run select query on campaign1 to count number of records.
What i'm doing right now is .
-Select from campign_list
-loop through all campaign_table_names and run select query individually
Is there a way to do this using a single query
something like this
select campaign_name,(SELECT COUNT(*) FROM c.campaign_name) as campcount from campaign_list c
SQLFiddle : http://sqlfiddle.com/#!9/b766d/2
It's not possible inside a single query to build it dynamically but it's possible to cheat. Especially if there are only two linked tables.
I've listed two options
left outer join both tables
select campaign_name,
coalesce(c1.campaign_details, c2.campaign_details)
from campaign_list c
left join campaign1 c1 using (id)
left join campaign2 c2 using (id);
union all two different selects
select campaign_name,
campaign_details
from campaign_list c
join campaign1 c1 using (id)
union all
select campaign_name,
campaign_details
from campaign_list c
join campaign2 c2 using (id);
sqlfiddle
Combine your campaign tables to 1 table and add an column named 'type' (int).
campaign_items tables:
item_id item_details item_type
1 'some detail' 1
2 'some detail' 1
3 'some other detail' 2
4 'some other detail' 2
campaign_lists table
campaign_id campaign_name
1 'campaign1'
2 'campaign2'
Then you can use the following select statement:
SELECT campaign_name, (SELECT COUNT(*) FROM campaign_items WHERE item_type = campaign_id) as campaign_count
FROM campaign_lists
Oops, writing took me so long that you got this answered by Colin Raaijmakers already. Well, I'll post my answer anyway in spite of being more or less the same answer. Maybe my elaboration helps you see the problem.
Your problem stems from a bad database design. A database is made to order data and its relations. A CD database holds albums, songs, artists, etc. A business database may hold items, warehouses, sales and so on. Your database holds table names. [... time for thinking :-) ]
(When writing a DBMS you would want to store table names, column names, constraints etc., but I guess I am right supposing that you are not writing a new DBMS.)
So create tables that deal with your actual data. E.g.:
campain_type (id_campain_type, description, ...)
campain (id_campain, id_campain_type, campain_date, ...)
campain_type
id_campain_type description
1 Type A
2 Type B
3 Type C
campain
id_campain id_campain_type date
33 1 2015-06-03
85 2 2015-10-23
97 2 2015-12-01
query
select
ct.description,
(select count(*) from campain c where c.id_campain_type = ct.id_campain_type) as cnt
from campain_type ct;
result
description cnt
Type A 1
Type B 2
Type C 0

Select rows based on values from two tables

I got the following tables in my mysql database: http://i.gyazo.com/8da933221a20ecb0e8f4a8073a2a5b41.png
table: ACCOUNTS
ID NAMN
-- -----
1 Name1
2 Name2
3 Name3
4 Name4
table: SUBBED
SUBSCRIBER RECEIVER
---------- --------
1 4
1 3
I would like to select ID, NAME from ACCOUNTS where account X (lets say the one with ID 1) isn't subscribed to.
If you look at the image, you can see that the account with NAME = Name1 is subscribed to Name3 and Name4. In this case, the query should return the second row from ACCOUNTS where ID = 2.
Does someone know what the query might look like?
You probably just want to left join the tables together, and then find the ones that don't match. Something like this:
select a1.*
from accounts a1
left join subbed s1
on a1.id = s1.receiver
and s1.subscriber = 1
where s1.subscriber is null and a1.id <> 1;
demo here
You can try something like this.
SELECT ID, NAME FROM ACCOUNTS WHERE ID NOT IN (SELECT RECEIVER FROM SUBBED)
Hope it helps.
Select ID, NAME
From ACCOUNTS
Where ID Not In (Select RECEIVER
From SUBBED
Where SUBSCRIBER = (Your X))

SQL filtering using an array

I have the following tables in my database:
Table: Employee
ID Name
-- ----
1 Mike
2 Peter
3 Daniel
Table: Location
EmployeeID City
---------- ----
1 Berlin
1 Stuttgart
1 München
2 Hamburg
3 Stuttgart
3 Berlin
The Employee table contains information about the employees. The Location table contains information about the locations the employees have their projects in (e.g Mike has projects in Berlin, Stuttgart, and München).
What I want to do now is to filter employees by given locations in an array but still retrieve all the locations of each employee. For example, filtering by the array ["Berlin", Stuttgart] should return the following result:
ID Name City
-- ---- ----
1 Mike Berlin, Stuttgart, München
3 Daniel Stuttgart, Berlin
I know that I can use GROUP_CONCAT() to concatenate the locations. But how can I do the filtering? I need to be able to do it using SQL.
Apply WHERE condition to get EmployeeID from Location table:
SELECT
Employee.*,
GROUP_CONCAT(Location.City)
FROM
Employee
INNER JOIN Location
ON Employee.ID=Location.EmployeeID
INNER JOIN
(SELECT DISTINCT
EmployeeID
FROM
Location
WHERE
City IN ('Berlin', 'Stuttgart')) AS IDS
ON Employee.ID=IDS.EmployeeID
GROUP BY
Employee.ID
-check the fiddle.
Alternative solution would be to use HAVING clause with plain query and INSTR(), for example, but I don't recommend you to do it because comparing in HAVING will be slow and, besides, list of values will produce multiple comparisons.
You can use below query:
SELECT
a.id,a.`name`,GROUP_CONCAT(b.city)
FROM employee a
JOIN
(SELECT DISTINCT employeeid,city FROM location WHERE location IN ('Berlin', 'Stuttgart')) b
ON a.id=b.employeeid
GROUP BY a.id;

Mysql error: Subquery returns more than 1 row (but I want it to - I want to select a vector on each row)

For the sake of simplicity, let's say I have tables users and interests
users
id | name
---------
1 | amy
2 | brian
3 | carole
interests
uid | interest
--------------
1 | apples
3 | catfish
3 | cobwebs
3 | cryogenics
What I want to get back is output that looks something like
name | interests
----------------
amy | apples
brian |
carole| catfish, cobwebs, cryogenics
Where interests could be a string consisting of the concatenation of all relevant values with some delimiter, or a vector of discrete values. I'm interested in dumping this to a file, rather than putting it in a table or doing any kind of further SQL stuff with it. Doing
SELECT name, (SELECT interest from interests where uid=id) as interests from users;
Is giving me the error I mentioned in the title. Is this just not possible in the SQL paradigm? I know I can dump a join of these tables to a file, and then aggregate the values I need using a python script or something, but this feels inelegant.
try this
SELECT name , group_concat(interest) as interests from interests
LEFT JOIN users on users.id = interests.uid
GROUP BY name
DEMO HERE
update:
if you want spaces do this group_concat(interest SEPARATOR ', ')
SELECT u.name, i.interest
FROM users AS u, interests AS i
WHERE u.uid = i.id
Try a join instead, this might work.
You might be getting errors because of the ordering of your select and from statements, or do you need to have a comma after name. Like:
SELECT name, ( *then your select statement here ...* )

MySQL get all related IDs from a table matching an array

I'm facing a problem while trying to retrieve all productIDs from a table if they match all items in an array, in this case, return products only if they contain every ingredient the user searched for.
Table looks like this
ID produktID ingredientID
----------------------------
1 418 1
2 418 2
3 418 3
4 416 4
5 411 1
6 411 5
7 411 6
I join this table from a products table where the main information is stored. The aim of the query should be to retreive a productID only when all ingredientIDs match with the given array. I've tried using WHERE ingredientID IN(1,5,6) but it always turns out to be an OR statement, returning every ID where any of the ingredients are matched.
So for example, if I pass (1,5,6) or (5,6) the product ID 411 should be returned, but if I pass (2,5,6) it should not.
The query I tried looks like this (simplified, it's part of a 5 way join to other relations like brands and catgories)
SELECT productID FROM products_ingredients_mm WHERE ingredientID IN (1,5,6) GROUP BY productID
but the result contains 418 aswell. How do I get it to match?
I hope I was able to describe the problem in an understandable way, it's really hard for me to wrap my head around it to ask a question.
This is called Relational Division.
SELECT produktID
FROM tableName
WHERE ingredientID IN (1,5,6)
GROUP BY produktID
HAVING COUNT(*) = 3
SQLFiddle Demo
If a unique constraint was not enforce on ingredientID for every produktID, then you need to use DISTINCT
SELECT produktID
FROM tableName
WHERE ingredientID IN (1,5,6)
GROUP BY produktID
HAVING COUNT(DISTINCT ingredientID) = 3
SQLFiddle Demo
Other Source
Relational Division
Try this:
SELECT pi.productID, p.productName
FROM products_ingredients_mm pim
INNER JOIN products p ON pim.productID = p.productID
WHERE ingredientID IN (1,5,6)
GROUP BY productID
HAVING COUNT(DISTINCT ingredientID) = 3