sql query implement two count in one - mysql

SELECT (select count(u.ag_code)
from table1 as u inner join table2 as tc
on u.industry_id=tc.tempcatid
where u.ag_code!=0) as agnt,
(select count(u.ag_code)
from table1 as u inner join table2 as tc
on u.industry_id=tc.tempcatid where u.ag_code=0),as dircus,
tc.catename from table1 as u inner join table2 as tc
where u.industry_id=tc.tempcatid
group by tc.tempcatid
this query have error
i need two count and category name in one query
this is the condition for count
ag_code!=0
ag_code=0
in table1 have column ag_code (this have 0 and nonzero value)
my result need like this
Full Texts
agent customer catename
11 3 Real Estate
15 1 Automobile
3 0 Medical
34 77 Business
1 45 Travel & Hotels
11 3 Construction & Engineering

SELECT tc.catename,
count(case when u.ag_code!=0 then 1 end) agnt,
count(case when u.ag_code =0 then 1 end) dircus
from table1 as u
inner join table2 as tc on u.industry_id=tc.tempcatid
group by tc.tempcatid, tc.catename

Hi There you might be able to use the below example to get back the result you require.
Select SUM(Inactive) Inactive ,SUM(Active) Active FROM
(
Select Count(t1.UserId) Inactive,0 Active
FROM
(select * from users where inactive=1) as t1
UNION
SELECT 0 Inactive,Count(t2.UserId) Active FROM
(select * from users where inactive=0) as t2
) as result

Related

Join three tables and subtract sum of column from a column data

I have three tables accounts, receivables and receiveds .
My basic table is receivables I want to get the names from the account table and then subtract the sum of received column in receiveds table form the receivable column in receivables table with same ref numbers. i want to ignore if the balance is zero.
accounts
id
name
22
John
23
Kahn
24
Falis
25
Haseni
26
Gent
receivables
id
receivable
Ref
22
70
A1
24
100
A2
26
60
A3
24
15
A4
receiveds
ref
id
received
A1
22
30
A2
24
60
A1
22
40
A3
26
20
A2
24
10
desired results
id
name
ref
receivable
received
balance
total_id_balance
24
Falis
A2
100
70
30
45
26
Gent
A3
60
20
40
40
24
Falis
A4
15
0
15
45
I have tried this code but it's not working for me
SELECT *
FROM receivables AS rvb
LEFT JOIN accounts AS acc
ON rvb.id = acc.id
LEFT JOIN (SELECT SUM(received) as sum_rvd FROM receiveds) AS rvd
ON acc.id = rvd.id where rvb.receivable>rvd.sum_rvd
INNER JOINs filter out NULL values and the HAVING clause removes zero-balance rows.
SELECT
accounts.* ,
ra.receivable,
rd.received,
ra.receivable - rd.received as balance
FROM accounts
INNER JOIN ( SELECT id, SUM(receivable) as receivable FROM receivables GROUP BY id ) ra
ON ra.id = accounts.id
INNER JOIN ( SELECT id, SUM(received) as received FROM receiveds GROUP BY id ) rd
ON rd.id = accounts.id
HAVING balance > 0
UPDATE
With a ref field we just need to add it as another grouping field for subselects, and change second INNER JOIN to LEFT JOIN (actually looks like it was a mistake from the start, coz we missed entries without receiveds that still had positive balance). Also changing received field to a COALESCE to get zeroes instead of NULL's (indicating non existing rows in a receiveds table).
Since you need an overall per-id total_id_balance field, the natural way to grab it - is using window functions. Note, they are supported only for MySQL 8.0+.
So the resulting query looks like this:
SELECT
accounts.* ,
ra.ref,
ra.receivable,
COALESCE(rd.received, 0) as received,
ra.receivable - COALESCE(rd.received, 0) as balance,
SUM( ra.receivable - COALESCE(rd.received, 0) ) OVER ( PARTITION BY id ) as total_id_balance
FROM accounts
INNER JOIN ( SELECT id, SUM(receivable) as receivable, ref FROM receivables GROUP BY id, ref ) ra
ON ra.id = accounts.id
LEFT JOIN ( SELECT id, SUM(received) as received, ref FROM receiveds GROUP BY id, ref ) rd
ON
rd.id = accounts.id
AND
ra.ref = rd.ref
HAVING balance > 0
ORDER BY ref
This work for me -
EDIT-
Add support for non-unique id in receivables
SELECT acc.id ,acc.name, res.receivable, res.received, (res.receivable - res.received) AS balance
FROM accounts AS acc JOIN
(SELECT recv.id, recv.receivable, rec.received
FROM (
SELECT id, SUM(receivable) AS receivable
FROM receivables
GROUP BY id) AS recv JOIN
(SELECT id, SUM(received) AS received
FROM receiveds
GROUP BY id) AS rec ON rec.id = recv.id
WHERE rec.received < recv.receivable) AS res ON res.id = acc.id;
Assuming it is possible to have an id in receivables without a corresponding id in receiveds, the second join needs to be a LEFT JOIN and you need to handle the NULLs in your SELECT list -
SELECT
a.*,
ra.receivable,
IFNULL(rd.received, 0) received,
ra.receivable - IFNULL(rd.received, 0) balance
FROM accounts a
INNER JOIN (
SELECT id, SUM(receivable) receivable
FROM receivables
GROUP BY id
) ra
ON a.id = ra.id
LEFT JOIN (
SELECT id, SUM(received) received
FROM receiveds
GROUP BY id
) rd
ON a.id = rd.id
HAVING balance > 0;
You can (and should) go a step further and remove the first derived table as it is unnecessary overhead -
SELECT
a.*,
SUM(ra.receivable) receivable,
IFNULL(SUM(rd.received), 0) received,
SUM(ra.receivable) - IFNULL(rd.received, 0) balance
FROM accounts a
INNER JOIN receivables ra
ON a.id = ra.id
LEFT JOIN (
SELECT id, SUM(received) received
FROM receiveds
GROUP BY id
) rd
ON a.id = rd.id
GROUP BY id
HAVING balance > 0;
db<>fiddle

How to determine equaivalent groupings (recursively) in SQL?

I have a list of products identified by their SKUs. To simplify it, I just name them as A, B, C, D,... here. Each of these SKUs has been assigned by default an already existing GroupID, for simplicity I just number them as 1, 2, 3,... here.
The same GroupID would mean "These SKUs are equivalent, so it is ok to use/buy either one of them, as it makes no difference".
The problem is, some SKUs show up more than once as they come from a different buying source, but as they come from a different source, they have a different grouping.
The goal is therefore to consolidate the grouping and make sure they have the same groupings.
I already apologize if my illustration may not be super pretty, but I'm trying. Here's a small data table sample on how the raw data looks like (first line is the column names):
Source SKU GroupID
Seller1 A 1
Seller1 B 1
Seller1 C 1
Seller2 B 2
Seller2 D 2
Seller2 E 2
Seller3 A 3
Seller3 B 3
Seller4 F 4
Seller4 G 4
Seller4 H 4
The result should be like:
Source SKU GroupID
Seller1 A 1
Seller1 B 1
Seller1 C 1
Seller2 B 1
Seller2 D 1
Seller2 E 1
Seller3 A 1
Seller3 B 1
Seller4 F 4
Seller4 G 4
Seller4 H 4
Basically, if Any SKU in GroupID X is a subset of GroupID Y, then GroupID Y = GroupID X. But that should be applied on all GroupIDs, so it appears to be recursive.
I wish I could show the code that I tried already and I tried already for a few days, but I literally only managed to produce garbage.
In C# I'd know how to deal with this, but I can't seem to wrap my head around SQL as I am not that experienced and unfortunately I would need this in SQL.
I would be thankful for any kind of help, even if it's just a hint or direction you guys would suggest I should try. Thanks a lot!
You want a correspondence between groups, which you can calculate with a recursive CTE:
with recursive tt as (
select distinct t1.groupid as groupid1, t2.groupid as groupid2
from t t1 join
t t2
on t1.sku = t2.sku
),
cte as (
select tt.groupid1, tt.groupid2, concat_ws(',', tt.groupid1, tt.groupid2) as visited
from tt
union all
select cte.groupid1, tt.groupid2, concat_ws(',', visited, tt.groupid2)
from cte join
tt
on cte.groupid2 = tt.groupid1
where find_in_set(tt.groupid2, cte.visited) = 0
)
select groupid1, min(groupid2) as overall_group
from cte
group by groupid1;
You can then join this back to the original table to get the "overall group":
with recursive tt as (
select distinct t1.groupid as groupid1, t2.groupid as groupid2
from t t1 join
t t2
on t1.sku = t2.sku
),
cte as (
select tt.groupid1, tt.groupid2, concat_ws(',', tt.groupid1, tt.groupid2) as visited
from tt
union all
select cte.groupid1, tt.groupid2, concat_ws(',', visited, tt.groupid2)
from cte join
tt
on cte.groupid2 = tt.groupid1
where find_in_set(tt.groupid2, cte.visited) = 0
)
select t.*, g.overall_group
from t join
(select groupid1, min(groupid2) as overall_group
from cte
group by groupid1
) g
on t.groupid = g.groupid1;
Here is a db<>fiddle.
Note: Your sample data is rather "complete" so you don't need a recursive CTE for that particular data. However, I am guessing that your real groups have a bit less overlap in which case recursion is necessary.
First is to get all those sellers with subsets based on count. then filter using Group By
select table1.Source, SKU, case when table1.Source = t6.Source and t6.cnt > 1 then 1 else 2 end as GroupID
from table1
left join
(select t5.Source, count(t5.cnt) as cnt from (
select distinct t4.Source, t4.cnt from (
select t3.Source, count(t3.SKU) as cnt from (
select t1.Source, t1.SKU from table1 t1
left join table1 t2 on t2.SKU = t1.SKU ) t3
group by t3.Source, t3.SKU
order by t3.Source) t4) as t5
group by t5.Source) t6 on t6.Source = table1.Source

SQL replace data in table1 from table2

Hello i have 2 tables in MySQL DB
status
id, name, date, status
1 server1 datum 0
2 server2 datum 999
3 server3 datum 999
4 server4 datum 0
cis
id, ,url
0 img/offline.png
1 img/server1.png
2 img/server2.png
3 img/server3.png
4 img/server4.png
999 img/online.png
i want to select id and status from status and i want to replace both server_id a and status with url from cis. But i dont know fi this is posible to do or do i need to create a third table for the online/ofline url?
i want to join the tables so that the select returns as this
id, status
img/server1.png, img/offline.png
img/server2.png, img/online.png
img/server3.png, img/online.png
img/server4.png, img/offline.png
According to your comments, you tried the following query:
select s.id,s.name,s.date,s.status,c1.url as serverurl,c2.url as statusurl
from status s left join cis c1 on s.id=c1.id left join cis c2 on s.status=c2.id
This returns the correct resultset, but if I understand what you are looking for, you want this query:
SELECT c1.url AS id, c2.url AS status FROM `status` s
LEFT JOIN `cis` c1 ON s.id = c1.id
LEFT JOIN `cis` c2 ON s.status = c2.id
c1.url is aliased as id and c2.url is aliased as status

How to get records from two tables with multiple where conditions

I have a two tables one is Userregistration and second is user_verificationcode from which i have to get only those record whose email and mobile status are 1.Below are my table structure
Userregistration table
........................................
id fullname mobile_no email
.........................................
5 varun 12344567 abc#gmail
6 nitin 12345678 def#gmail
user_verificationcode
.............................................
id user_id codetype status
............................................
1 5 email 0
2 5 mobile 1
3 6 email 1
4 6 mobile 1
I want this kind of output
........................................
id fullname mobile_no email
.........................................
6 nitin 12345678 def#gmail
For this i have used below query but its not working i am not getting how to achieve this.
SELECT * FROM Userregistration
INNER JOIN user_verificationcode ON Userregistration.`id`=user_verificationcode.`user_id`
where user_verificationcode.`codetype`='email'
and user_verificationcode.`status`='1'
and user_verificationcode.`codetype`='mobile'
and user_verificationcode.`status`='1'
SELECT r.*
FROM Userregistration r
INNER JOIN user_verificationcode ve ON r.id = ve.user_id
and ve.codetype = 'email'
and ve.status = 1
INNER JOIN user_verificationcode vm ON r.id = vm.user_id
and vm.codetype = 'mobile'
and vm.status = 1
or
SELECT *
FROM Userregistration
where id in
(
select user_id
from user_verificationcode
group by user_id
having sum(codetype = 'email' and status = 1) > 0
and sum(codetype = 'mobile' and status = 1) > 0
)
You probably want to return only Userregistration fields, since you already know the info contained in user_verificationcode table. In this case you can use the following query:
SELECT t1.*
FROM Userregistration AS t1
JOIN (
SELECT user_id
FROM user_verificationcode
WHERE codetype IN ('mobile', 'email')
GROUP BY user_id
HAVING COUNT(DISTINCT codetype) = 2 AND SUM(status <> 1) = 0
) AS t2 ON t1.id = t2.user_id
You may would like to do something like this
SELECT Userregistration.id, Userregistration.fullName, Userregistration.mobile_no,
Userregistration.email FROM Userregistration
INNER JOIN user_verificationcode
ON Userregistration.id=user_verificationcode.user_id
WHERE user_verificationcode.codetype='email' AND user_verificationcode.status = 1
SELECT Userregistration.id,
Userregistration.fullName,
Userregistration.mobile_no,
Userregistration.email
FROM Userregistration
INNER JOIN user_verificationcode ON
Userregistration.id=user_verificationcode.user_id AND
user_verificationcode.status=1
WHERE user_verificationcode.codetype='email' AND
user_verificationcode.codetype='mobile'

Select distinct totals from access tables

I have three tables: T_O, T_C, & T_D they each have a date (run_date) and count column.
I need to select the data to show a summary by date for each count. I cannot get the nested sql to make it look right.
Needs to be grouped by Run Date. End result should look like this:
Run_Date Total Defects Not Closed Closed
05/29/13 178 100 78
06/04/13 204 103 101
06/11/13 234 114 120
I assume the three tables each have two columns: Run_Date and Total Defects, Not Closed or Closed. If you have a table with all the run dates in it, something like this will work:
SELECT
RunDates.Run_Date,
T_D.[Total Defects],
T_O.[Not Closed],
T_C.[Closed]
FROM ((
RunDates
LEFT JOIN T_C ON RunDates.Run_Date = T_C.Run_Date)
LEFT JOIN T_O ON RunDates.Run_Date = T_O.Run_Date)
LEFT JOIN T_D ON RunDates.Run_Date = T_D.Run_Date
If not, you will need to construct one using a UNION (not UNION ALL):
SELECT
RunDates.Run_Date,
T_D.[Total Defects],
T_O.[Not Closed],
T_C.[Closed]
FROM ((
(SELECT Run_Date FROM T_C
UNION
SELECT Run_Date FROM T_O
UNION SELECT Run_Date FROM T_D) AS RunDates
LEFT JOIN T_C ON RunDates.Run_Date = T_C.Run_Date)
LEFT JOIN T_O ON RunDates.Run_Date = T_O.Run_Date)
LEFT JOIN T_D ON RunDates.Run_Date = T_D.Run_Date