I have the following 2 tables
tableA a (id, name, surname, program, date)
tableB b (id, aid, name, surname, extracard)
with tableA.id = tableB.aid (1 to n relationship)
Sample data for tableA:
| ID | NAME | SURNAME | PROGRAM | DATE | EXPIRES |
----------------------------------------------------------
| 1 | TOM | JONES | 1,2,3 | 12/8/2012 | 12/8/2013 |
| 2 | JAMIE | OLIVER | 4,5,6 | 15/8/2012 | 15/8/2013 |
Sample data for tableB:
| ID | AID | NAME | SURNAME | CARD |
-------------------------------------
| 1 | 1 | ANNE | JONES | 1 |
| 2 | 1 | JACK | BOWER | 0 |
| 3 | 2 | KATE | PERRY | 1 |
| 4 | 2 | JOHN | DOE | 0 |
| 5 | 2 | HARRY | POTTER | 0 |
In the results, each member of tableB should have all values (program, date, expires, etc...) from tableA and display only the name, surname from tableB in the same column (coalesce??). Also, I need to use a between clause for a.id between (%id1 and %id2) and also a WHERE statement for selecting rows where tableB.card=1
| a.ID | NAME | SURNAME | PROGRAM | DATE | EXPIRES |
------------------------------------------------------------
| 1 | TOM | JONES | 1,2,3 | 12/8/2012 | 12/8/2013 |
| 1 | ANNE | JONES | 1,2,3 | 12/8/2012 | 12/8/2013 |
| 2 | JAMIE | OLIVER | 4,5,6 | 15/8/2012 | 15/8/2013 |
| 2 | KATE | PERRY | 4,5,6 | 15/8/2012 | 15/8/2013 |
SELECT * FROM
( (SELECT a.id ,a.name,a.surname,a.program,a.date,a.expires
from tableA a left outer join tableB b
on b.aid=a.id
where b.card=1 and (a.id between '1' and '2'))
UNION ALL
(SELECT a.id ,b.name,b.surname,a.program,a.date,a.expires
from tableA a left outer join tableB b
on b.aid=a.id
where b.card=1 and (a.id between '1' and '2'))) t
ORDER BY id
EDITED:
Please refer to http://sqlfiddle.com/#!2/d8227/1
Are you looking for -
(SELECT a.id, name, surname, program, date, expires FROM tableA a WHERE a.id BETWEEN '%id1' and '%id2')
UNION
(SELECT a.id, b.name, b.surname, program, date, expires FROM tableB b LEFT JOIN tableA a ON b.aid=a.id WHERE b.card=1 AND (a.id between '%id1' and '%id2') )
ORDER BY a.id ASC
(select a.ID,a.NAME,a.SURNAME,a.PROGRAM,a.DATE,a.EXPIRES from tableA a where ...)
Union All
(select a2.ID,b.NAME,b.SURNAME,a2.PROGRAM,a2.DATE,a2.EXPIRES from tableB b
left join tableA a2 on b.aid = a2.id where ...);
You can choose left/inner join as per your need and where condition too with between clause like.. where id between 2 and 8 or where id > 2 and id < 8.
Related
I have two tables. I want to compare table A with B and get the missing date from with name of the user.
TABLE A
|----|----------|------------|
| 1 | king | 2020-08-01 |
| 2 | king | 2020-08-02 |
| 3 | queen | 2020-08-01 |
| 4 | queen | 2020-08-02 |
| 5 | rook | 2020-08-03 |
| 6 | bishop | 2020-08-01 |
| 7 | bishop | 2020-08-01 |
| 8 | queen | 2020-08-03 |
TABLE B
| id | working_date |
|----|--------------|
| 1 | 2020-08-01 |
| 2 | 2020-08-02 |
| 3 | 2020-08-03 |
EXPECTED OUTPUT
| name | missing_date |
|--------|--------------|
| king | 2020-08-03 |
| rook | 2020-08-01 |
| rook | 2020-08-02 |
| bishop | 2020-08-02 |
| bishop | 2020-08-03 |
Also, Along with it can I get the count of the missing dates for each user if possible?
You must cross join Table B to the distinct names of Table A and then left join Table A to filter out the matching rows:
select n.name, b.working_date missing_date
from TableB b
cross join (select distinct name from TableA) n
left join TableA a on a.name = n.name and a.working_date = b.working_date
where a.id is null
If you want to count the missing_dates use the same query and group by name:
select n.name, count(*) missing_dates
from TableB b
cross join (select distinct name from TableA) n
left join TableA a on a.name = n.name and a.working_date = b.working_date
where a.id is null
group by n.name
See the demo.
Results:
> name | missing_date
> :----- | :-----------
> king | 2020-08-03
> rook | 2020-08-01
> rook | 2020-08-02
> bishop | 2020-08-02
> bishop | 2020-08-03
and:
> name | missing_dates
> :----- | ------------:
> bishop | 2
> king | 1
> rook | 2
Getting distinct user names from Table A and joining it with Table B you can create all working date variations of the users. Then with not exists you can list missing dates:
SELECT A1.name, B.working_date
FROM B JOIN
(SELECT DISTINCT name
FROM A) A1
WHERE NOT EXISTS (
SELECT *
FROM A
WHERE A.name = A1.name
and A.working_date = B.working_date
)
For your last question finding missing counts you can use the below query:
SELECT S.name, COUNT(1) AS 'MissingDatesCount'
FROM (
SELECT A1.name, B.working_date
FROM B JOIN
(SELECT DISTINCT name
FROM A) A1
WHERE NOT EXISTS (
SELECT *
FROM A
WHERE A.name = A1.name
and A.working_date = B.working_date
)
) S
GROUP BY S.name
Go to the SqlFiddle
I have the following tables:
Table A:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ID | User | Enterpr_id |
| 1 | test1 | 1 |
| 2 | test2 | 2 |
| 3 | test3 | 3 |
| 4 | test4 | 4 |
| 5 | test5 | 1 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Table B:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Enterpr_id | Name |
| 1 | Nespresso |
| 2 | what |
| 3 | else |
| 4 | need |
| 5 | help |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
I have a foreign key on Enterpr_id with Table A, how can I make a count alternate and get the expected Output:
Nespresso - 2 users
what - 1 user
else - 1 user
need - 1 user
help - 0 user
That's a simple join:
select a.user, b.name
from tablea a
inner join tableb b on b.entrepr_id = a.entrepr_id
Edit: from your updated question, you seem to want aggregation and a left join:
select b.name, count(a.id) cnt_users
from tableb b
left join tablea a on a.entrepr_id = b.entrepr_id
group by b.entrepr_id, b.name
order by b.entrepr_id
It's a left join query with a count:
SELECT Name, COUNT(TableA.ID)
FROM TableB LEFT JOIN TableA ON TableB.Enterpr_id = TableA.Enterpr_id
GROUP BY TableB.Enterpr_id, TableB.Name;
using latest mariaDB release, I have the following table structure (trimmed for example)
Table A
+--------+------+
| id |name |
+--------+------+
| 1 | Bob |
| 2 | Jane |
+--------+------+
Table B
+--------+------+
| id |city |
+--------+------+
| 1 | abc |
| 2 | def |
| 3 | ghi |
| 4 | jkl |
+--------+------+
Pivot Table
+-----------+-----------+
| tableA_id | tableB_id |
+-----------+-----------+
| 1 | 1 |
| 1 | 3 |
| 2 | 3 |
| 2 | 4 |
+-----------+-----------+
is there a way to make it go from this output or will that need to be done php?
+--------+------+-------+
| id |name | city1 |
+--------+------+-------+
| 1 | Bob | abc |
| 1 | Bob | ghi |
| 2 | Jane | ghi |
| 2 | Jane | jkl |
+--------+------+-------+
to this:
+--------+------+----------+
| id |name | cities |
+--------+------+----------+
| 1 | Bob | abc ghi |
| 2 | Jane | ghi jkl |
+--------+------+----------+
using the below query currently
SELECT c.id, c.city1, p.id pid, p.first_name FROM city c
INNER JOIN pivot_tablet piv ON c.id = piv.city_id
INNER JOIN person p ON p.id = piv.person_id
use group_concat()
SELECT p.id,p.first_name,group_concat(c.city1 SEPARATOR ' ') as cities,
FROM pivot_tablet piv inner join city ON c.id = piv.city_id
INNER JOIN person p ON p.id = piv.person_id
group by p.id, p.first_name
create table #temp (row1 int,row2 int,row3 int,row4 varchar(20),row5 int,row6 varchar(20))
insert into #temp
select * from table3 join Table1 on Table1.id=Table3.idTable1 join table2 on table2.id = table3.idtable2
select row1,row4,
row6
= STUFF((
SELECT ', ' + t2.row6
FROM #temp t2
WHERE t1.row1 = t2.row1
FOR XML PATH('')
),1, 2, '')
FROM #temp t1
GROUP BY t1.row1,t1.row4
How to get name and manager name
+----+-----------+---------+
| id | name | manager |
+----+-----------+---------+
| 1 | bhupendra | 0 |
| 2 | shyam | 1 |
| 3 | ram | 1 |
| 4 | geeta | 2 |
| 5 | sita | 1 |
+----+-----------+---------+
i need result like
+-----------+-----------+
| name | manager |
+-----------+-----------+
| bhupendra | |
| shyam | bhupendra |
| ram | bhupendra |
| geeta | shyam |
| sita | bhupendra |
+-----------+-----------+
You could self-join the id column on the manager column:
SELECT e.name AS name, m.name AS manager
FROM employee e
LEFT JOIN employee m ON m.id = e.manager
You should use the same table twice using alias
select a.name, b.name as manager
from my_table a
left join my_table b on a.manager = b.id
Check this out
with recursive cte (id, name, parent_id) as (
select id,
name,
manager
from employee
union all
select p.id,
p.name,
p.manager
from employee e
inner join cte
on p.manager = cte.id
)
select * from cte;
I have two tables. One table is with master data
Table tbl1:
+-------------+------------+------------+
| ID | Name | Total |
+-------------+------------+------------+
| 1 | a | 10 |
| 2 | b | 5 |
| 3 | c | 4 |
| 4 | a | 4 |
+-------------+------------+------------+
Second table tbl2 contains child data. The key between tables is ID
Table tbl2:
+-------------+------------+
|id | qty |
+-------------+------------+
| 1 | 4 |
| 1 | 3 |
| 1 | 1 |
| 3 | 1 |
| 3 | 3 |
+-------------+------------+
I need to get output like this:
Output:
+-------------+------------+------------+
| name | sum_tot | sum_qty |
+-------------+------------+------------+
| a | 14 | 8 |
| b | 5 | 0 |
| c | 4 | 4 |
+-------------+------------+------------+
I had tried with this:
select tbl1.name, SUM(tbl1.total), SUM(tbl2.qty)
from tbl1
left join tbl2 ON tbl1.id = tbl2.id
GROUP by tbl1.name
The output that I get is:
Output:
+-------------+------------+------------+
| name | sum_tot | sum_qty |
+-------------+------------+------------+
| a | 34 | 8 |
| b | 5 |null |
| c | 8 | 4 |
+-------------+------------+------------+
Which is not correct.
Here is the sql fiddle:
The summary from first table is not in relation with second table. It seems that somehow query runs three times.
You can simply have a correlated sub-query that calculates the tbl2 sum:
select tbl1.name,
SUM(tbl1.total),
SUM(COALESCE((select SUM(tbl2.qty)
from tbl2
where tbl1.id = tbl2.id), 0)) as qty_tot
from tbl1
GROUP by tbl1.name
SELECT A.name, SUM(A.total) as sum_tot, COALESCE(B.sum_qty, 0) as sum_qty
FROM tbl1 A
LEFT JOIN (
SELECT id, SUM(qty) as sum_qty
FROM tbl2
GROUP BY id
) B ON B.id = A.id
GROUP BY A.name
select tbl1.name, SUM(tbl1.total), SUM(COALESCE(tbl2.qty, 0))
from tbl1
left join tbl2 ON tbl1.id = tbl2.id
GROUP by tbl1.name