How to use UNION and GROUP_CONCAT together - mysql

I have a problem with the correct syntax to use UNION and GROUP_CONCAT in this situation:
I have 4 tables:
base: Is the main table with a lot of columns.
mm: Is a mm table that points to the next two tables using a 'tablenames' field.
t1 and t2 that stores data related.
Records in 'base' tables can have many related records in t1 and t2 through the mm table.
I'm creating a VIEW in MySQL and I need all those related records are displayed in a single column separated by commas.
This is the base MySQL code:
SELECT base.uid, t1.nombre_es
FROM base
INNER JOIN mm
ON mm.uid_local=base.uid
INNER JOIN t1
ON mm.uid_foreign=t1.uid WHERE mm.tablenames = 't1'
UNION
SELECT base.uid, t2.nombre_es
FROM base
INNER JOIN mm
ON mm.uid_local=base.uid
INNER JOIN t2
ON mm.uid_foreign=t2.uid WHERE mm.tablenames = 't2'
Thanks in advance.
I could do it using two VIEWS, the first using the code above with the name 'viewtest", and the second with this code:
SELECT base.uid,
GROUP_CONCAT(DISTINCT vi.nombre_es ORDER BY vi.nombre_es SEPARATOR ',') as nombre
FROM base
INNER JOIN viewtest as vi
ON vi.uid=base.uid
GROUP BY uid
Now the question is ¿How can I join this two views in a single view?

You can use derived tables from queries. Next is an example of how you can use them.
SELECT GROUP_CONCAT( f )
FROM (
SELECT 1 AS f # <-- QUERY #1
UNION
SELECT 2 AS f # <-- QUERY #2
UNION
SELECT 3 AS f # <-- QUERY #3
) AS T
Basically, you can use any SELECT query as an aliased table. Then, you can apply any aggregate functions you need to that aliased query.

Related

What other approch I can use to select * while inner joining multiple tables?

I want to create View by selecting all data from multiple tables, but the error I got saying that I have duplicate columns
CREATE VIEW All_Data AS
SELECT *
FROM table1 tb1
INNER JOIN table 2 tb2 ON tb1.ID = tb2.ID
INNER JOIN table 3 tb3 ON tb2.ID = tb3.ID
INNER JOIN table 4 tb4 ON tb3.ID = tb4.ID
INNER JOIN table 5 tb5 ON tb4.ID = tb5.ID
INNER JOIN table 6 tb6 ON o.SpecialID = tb6.ID
INNER JOIN table 7 tb7 ON tb6.ID = tb7.ID
LEFT JOIN table 8 tb8 ON tb7.ID = tb8.ID
However, I am still having the same problem. I want to know is there a faster way to do that instead using alias selecting each column one by one.
DISTINCT won't help as its talking about duplicate columns vs duplicate rows.
Its the * that is causing the columns from all tables, with duplicate column names to be returned. You'll need to replace the * with explicit columns and alias them like below if both are needed.
SELECT p.created_date as product_created_date, order.created_date as order_created date .....
Note using a view isn't a needed pattern. Selects of exactly the right result are normally sufficient. Selects on views can suffer in performance as they are more complicated for MySQL to optimize. They are useful if you need an explicit GRANT on the them for a specific user however.
You need to provide the full list of columns that you want to be part of the view. There is no shortcut.
But yes, to ease your work, If you want the comma separated list of the column names of the table then you can use the following query for each table and put their columns in your select query. You will then just need to alias the columns which have same names.
Select listagg('pd.'|| column_name, ',')
Within group (order by column_id)
From user_tab_columns
Where table_name = 'your_table_name_in_capital';
Note that you need to replace 'pd.' for each table with the table alias in your query.

SQL: selecting the set of A not B

I have Two tables: left one is users_projects, right one is projects:
I want to select the projects that user 3 is not participating in (only p_ID 5 and 7).
I've tried SELECT * FROM users_projects up INNER JOIN projects p ON p.p_ID=up.p_ID WHERE up.u_ID!=3
but that also returns me p_ID 1 which both user 2 and 3 are a part of.
Thanks for your help!
A solution with LEFT JOIN:
SELECT
*
FROM
projects p LEFT JOIN users_projects up ON (p.p_ID = up.p_ID AND up.u_ID = 3)
WHERE
up.u_ID IS NULL
Basically select all Projects and join them with the user_projects of the desired user. Left join makes all rows from the project table appear even if the is no corresponding row in the users_projects table. These rows have all fields from the users_projects set to NULL, so we can just select those.
This is not a JOIN query, but a query with a non-correlated sub-select with a NOT IN() predicate.
I hope the columns of the projects table are enough ...
SELECT
*
FROM
( SELECT 1,'Apple' -- input data, don't use in 'real' query
UNION ALL SELECT 5,'Banna' -- input data, don't use in 'real' query
UNION ALL SELECT 7,'Carrot' -- input data, don't use in 'real' query
UNION ALL SELECT 8,'Durian') -- input data, don't use in 'real' query
projects(p_id,p_name)
WHERE p_id NOT IN (
SELECT
p_id
FROM
( SELECT 2,1 -- input data, don't use in 'real' query
UNION ALL SELECT 2,5 -- input data, don't use in 'real' query
UNION ALL SELECT 2,7 -- input data, don't use in 'real' query
UNION ALL SELECT 3,1 -- input data, don't use in 'real' query
UNION ALL SELECT 3,8) -- input data, don't use in 'real' query
users_projects(u_id,p_id)
WHERE u_id=3
)
;
p_id|p_name
7|Carrot
5|Banna

mysql count records by subquery on same table

my problem is that i am joining 4 tables by left join so i cant use group by rather than sub query.
but how do i get the count of main table based on specific column
any tips .
Is it possible.
Thanks in advance
I have tried this way.
SELECT * ,sql_1.trans
FROM table1 a
LEFT JOIN table b ON condition
LEFT JOIN ( SELECT count(*) trans,dentist_id as did3 FROM table1
GROUP BY dentist_id
) sql_1 ON did3=a.dentist_id
WHERE a.current_tab='pack'

How to get information from two tables

I want to extract some information from two different table in one database,
[(first table): id-nbrNight-........]
[(second table): id-........]
I want to extract the nbrNight from the first table & the id from the second table:
so in my case I write this, but I don't know how to rassemble this two line in one line:
SELECT sum(nbrNight) as night FROM firsttab
SELECT count(`id`) as id FROM secondtab
I wirte this to rassemble this two line:
SELECT sum(nbrNight) as night,count(`id`) FROM firsttab,secondtab
But it doesn't work!
You can use UNION to combine the result from two query like
SELECT sum(nbrNight) as night FROM firsttab
UNION
SELECT count(`id`) as id FROM secondtab
(OR) do a JOIN with both tables using a common column between them (if any present) like below (assuming id is the common column between them)
SELECT sum(t1.nbrNight) as nightsum, count(t2.`id`) as idcount
FROM firsttab t1 JOIN secondtab t2 ON t1.id = t2.id
One option is to use the queries as inline views; reference those queries as a rowsource (like a table) in another query.
Since each query returns a single row, you can safely perform a JOIN operation, without need for any join predicate (aka CROSS JOIN).
For example:
SELECT f.night
, s.id
FROM ( SELECT SUM(nbrNight) AS night FROM firsttab ) f
CROSS
JOIN ( SELECT COUNT(id) AS id FROM secondtab ) s
Another option (since both queries are guaranteed to return exactly one row, if they don't return an error) is to include the query in the SELECT list of another query. It's not necessary to include a column alias in the subquery, but we can assign an alias.
For example:
SELECT ( SELECT SUM(nbrNight) FROM firsttab ) AS night
, ( SELECT COUNT(id) FROM secondtab ) AS id
If either of the queries were returning more than one column, then the approach in the first example will still work. The inline view queries can return multiple expressions, and we can reference those expressions in the outer query. With the pattern in the second example, that imposes a restriction that the subqueries must return only one expression (one column).
As an example to demonstrate an inline view returning more than one column, the inline view f returns three expressions:
SELECT f.night
, f.cnt
, f.min_nbr
, s.id
FROM ( SELECT SUM(nbrNight) AS night
, COUNT(nbrNight) AS cnt
, MIN(nbrNight) AS min_nbr
FROM firsttab
) f
CROSS
JOIN ( SELECT COUNT(id) AS id FROM secondtab ) s

MySQL, merging 2 or more tables before execute SELECT DISTINCT query?

I want to calculate how many unique logins from 2 (or probably more tables).
I tried this:
SELECT count(distinct(l1.user_id))
FROM `log_1` l1
LEFT JOIN `log_2` l2
ON l1.userid = l2.userid;
But it gives me result of l1. If I didn't put l1 on li.userid (distinct), it said "ambiguous".
How do I combine the table, and then select unique login of the combined table?
EDIT:
Tested: I test the count(distinct(l1.userid)) and count(distinct(l2.userid)). It gives me different result
If you are using LEFT JOIN then you will get at least one row in the combined result for each row in l1, so the join is entirely unnecessary if you just want a distinct count. This would give you the same result as your query:
SELECT count(distinct(l1.user_id))
FROM `log_1` l1
Perhaps you want an INNER JOIN or UNION instead? A UNION will count a user if they appear in either table. An INNER JOIN will count them only if they appear in both tables. Here's an example of the UNION:
SELECT count(*) FROM (
SELECT distinct(user_id) FROM `log_1`
UNION
SELECT distinct(user_id) FROM `log_2`
) T1