I have three tables asrecord of students:
record of courses:
Map student and course:
I want to get records from table std_course where student are as 1,2,3 using query
select course_id from std_course where std_id in (1,2,3) group by course_id
It returns me course_id as 1 but here std_id=4 also exist against course_id=1
I need to select course_id where std_id are only 1,2,3
You can use sum() and select case, std_id above 3 will be 0
select * from (
select sum(case when std_id in (1, 2, 3) then 1 else 0 end) tot
, course_id
from std_course
group by course_id) t1
where t1.tot <= 3
You can try this using join:
select * from std_course left outer join course on course.id= std_course.course_id where std_id <=3
The query that work for me after the changings in query Answered by #ϻᴇᴛᴀʟ is:
select * from ( select sum(case when std_id in (1,2,3) then 1 else -1 end) tot , course_id from std_course group by course_id) t1 where t1.tot = 3
Related
After using UNION with two select queries, I'm getting following results
UserId Name Status
------ ------ --------
1 User1 Active
2 User2 Active
1 User1 InActive
3 User3 InActive
But the expected results is
UserId Name Status
---------------------
1 User1 Active
2 User2 Active
3 User3 InActive
Here what I need is, I want to group by column Id and get status as Active if any one result is active. How to form a SQL query for this?
Can anyone suggest query for any one of the following DB?
MSSQL
Oracle
MySQL
PostgreSQL
Edit:
This is the query I've tried in PostgreSQL
(SELECT DISTINCT User.Id,User.DisplayName,AppAccessToUsers.IsActive='1' AND User.IsActive='1' AS IsStatusActive
FROM Applications Left JOIN AppAccessToUsers ON (Applications.Id=AppAccessToUsers.ApplicationId)
Left JOIN User ON (AppAccessToUsers.UserId=User.Id) WHERE Applications.ClientId='e7e66c1b-b3b8-4ffb-844b-fc4840803265')
UNION
(SELECT DISTINCT User.Id,User.DisplayName,AppAccessToGroups.IsActive='1' AND Group.IsActive='1' AND UserGroup.IsActive='1' AND User.IsActive='1' AS IsStatusActive
FROM Applications Left JOIN AppAccessToGroups ON (Applications.Id=AppAccessToGroups.ApplicationId)
Left JOIN Group ON (AppAccessToGroups.GroupId=Group.Id) Left JOIN UserGroup ON (Group.Id=UserGroup.GroupId)
Left JOIN User ON (UserGroup.UserId=User.Id) WHERE Applications.ClientId='e7e66c1b-b3b8-4ffb-844b-fc4840803265')
Use this query,
SELECT UserId
,Name
,CASE WHEN min(status) = 'Active' THEN 'Active' ELSE 'InActive' END
FROM users GROUP BY UserId,Name
I would do the following, assuming a) your tables are called t1 and t2 (amend as appropriate for your actual table names) and b) the names for each userid in both tables are the same - ie. for userid = 1, both tables have the same name:
SELECT userid,
NAME,
MIN(status)
FROM (SELECT userid, NAME, status FROM t1
UNION ALL
SELECT userid, NAME, status FROM t2)
GROUP BY userid, NAME;
This works in Oracle, and I'm pretty sure it'll work in the other database platforms you mentioned.
N.B. I used MIN(status) since you appear to want a status of Active to override a status of Inactive, and A comes before I in the alphabet.
In Sql-server, you could use group by or Row_number like this
DECLARE #SampleData AS TABLE
(
UserId int,
Name varchar(20),
Status varchar(10)
)
INSERT INTO #SampleData
(
UserId,Name,Status
)
VALUES
(1,'User1', 'Active'),
(2,'User2', 'Active'),
(1,'User1', 'InActive'),
(3,'User3', 'InActive')
-- use row_number
;WITH temp AS
(
SELECT *, row_number() OVER(PARTITION BY sd.UserId ORDER BY sd.Status ) AS Rn
FROM #SampleData sd
)
SELECT t.UserId, t.Name, t.Status
FROM temp t WHERE t.Rn = 1
--or use group by
SELECT sd.UserId, sd.Name, min(sd.Status) AS status
FROM #SampleData sd
GROUP BY sd.UserId, sd.Name
Results:
UserId Name Status
1 User1 Active
2 User2 Active
3 User3 InActive
In case of MS Sql Server you can try row_number
;with cte as (
select top 1 with ties * from
( select * from #youruser
union all
select * from #youruser) a
order by row_number() over (partition by userid order by [status] desc)
) select * from cte where status = 'Active'
select your_table.* from your_table
inner join (
select UserId, min(Status) as st from your_table
group by UserId
) t
on your_table.UserId = t.UserId and your_table.Status = t.st
Note: if same UserId can have same Status more than 1 times, then this returns duplicated results.
;With cte (UserId, Name,Status)
AS
(
SELECT 1,'User1','Active' Union all
SELECT 2,'User2','Active' Union all
SELECT 1,'User1','InActive' Union all
SELECT 3,'User3','InActive'
)
SELECT UserId
,NAME
,[Status]
FROM (
SELECT *
,ROW_NUMBER() OVER (
PARTITION BY UserId
,NAME ORDER BY STATUS
) AS Seq
FROM cte
) dt
WHERE dt.Seq = 1
OutPut
UserId Name Status
-----------------------
1 User1 Active
2 User2 Active
3 User3 InActive
for postgres you can use CASE and bool_or, eg:
t=# with a(i,n,b) as (
values (1,'a','active'), (1,'a','inactive'), (2,'b','inactive'), (2,'b','inactive')
)
select i,n,case when bool_or(b = 'active') then 'active' else 'inactive' end
from a
group by i,n
;
i | n | case
---+---+----------
1 | a | active
2 | b | inactive
(2 rows)
Another approach:
Note : Group by is to remove duplicate
select
A.USERID, A.NAME,A.STATUS
from TAB_1 A
LEFT JOIN
(SELECT * FROM TAB_1 WHERE STATUS='Active') B
ON A.USERID=B.USERID
WHERE
( B.STATUS IS NULL OR A.STATUS=B.STATUS)
GROUP BY A.USERID, A.NAME,A.STATUS
ORDER BY A.USERID
;
Hello i am having two different table with same field created_date (datetime)
now i want records which counts daywise records with joining table i have done for individual counting as below query :
SELECT DATE(created_date), COUNT(*) FROM table1 GROUP BY DAY(created_date)
SELECT DATE(created_date), COUNT(*) FROM table2 GROUP BY DAY(created_date)
and i am getting results for individuals something like this:
RESULT I NEED :
DATE(created_date) count(table1) count(table2)
2016-12-01 10 3
2016-12-02 1 0
2016-12-05 1 0
2016-11-29 1 0
2016-11-30 4 1
Now i just want to join these result WITH INDIVIDUAL VIEW COUNT ACCORDING TO TABLE can anyone please help me out with this profile....
First take a UNION between your two tables, then use conditional aggregation to determine the counts for each of the two tables. Note that I introduce a field called table_name to keep track of data from each of the two tables.
SELECT t.created_date,
SUM(CASE WHEN t.table_name = 'one' THEN 1 ELSE 0 END) AS count_table_one,
SUM(CASE WHEN t.table_name = 'two' THEN 1 ELSE 0 END) AS count_table_two
FROM
(
SELECT DATE(created_date) AS created_date, 'one' AS table_name
FROM table1
UNION ALL
SELECT DATE(created_date), 'two'
FROM table2
) t
GROUP BY t.created_date
I used DATE consistently everywhere to make the query correct.
Try This:
SELECT created_date, sum(countTable1) countTable1,
sum(countTable2) countTable2
FROM (
SELECT DATE(created_date) created_date, COUNT(*) countTable1, NULL countTable2
FROM table1 GROUP BY DAY(created_date)
UNION ALL
SELECT DATE(created_date) created_date, NULL, COUNT(*) countTable2
FROM table2 GROUP BY DAY(created_date)) t GROUP BY t.created_date
You have a problem in your queries, you are grouping by DAY(date) and showing 'date' so the result will be first date with day(date), yet repeating it to avoid misunderstanding :)
select IFNULL(A.cd, B.cd), A.cnt, B.cnt from
(SELECT DAY(created_date) d, DATE(created_date) cd, COUNT(*) cnt
FROM table1 GROUP BY DAY(created_date)) as A
LEFT JOIN
(SELECT DAY(created_date) d, DATE(created_date) cd , COUNT(*) cnt
FROM table2 GROUP BY DAY(created_date)) B ON B.d = A.d
Its not too hard just use union if no need to allow duplicate row else use union all for all(means allow duplicate as well).
SELECT DATE(created_date), COUNT(*) FROM table1 GROUP BY DAY(created_date)
UNION
SELECT DATE(created_date), COUNT(*) FROM table2 GROUP BY DAY(created_date)
SELECT T.create_date,ISNULL(T.count,0)AS Counttable1,ISNULL(X.count,0)AS Counttable2 FROM(SELECT DATE(created_date) AS create_date,COUNT(*) as count FROM table1 GROUP BY DAY(created_date)) AS T LEFTJOIN(SELECT DATE(created_date) AS create_date, COUNT(*) as count FROM table2 GROUP BY DAY(created_date))AS X ON T.create_date=X.create_date
You actually need a SQL UNION. JOIN natuarually eliminate counts becuase the maytch fields. I.e. if you had 2016-12-01 in both table1 andtable2 then a JOIN on created_date would give you a count of 1 instead of a count of 2.
SELECT DATE(total.created_date), COUNT(*)
FROM (
SELECT created_date FROM table1
UNION ALL
SELECT created_date FROM table2) as total
GROUP BY total.created_date
HERE you simply union the two tables since they have a matching column name. Then you get back every date from both tables. That is in the inner query. The outer query then does the counting.
Hope that makes sense.
I have following 3 tables with duplicate id.I want to retrieve record with same id but having different name and date from all the 3 tables.I need query to get Expected result output.
CREATE TABLE Student1
(`id` int,`status` int,`amount` int , `Name` varchar(10), `date` varchar(55))
;
INSERT INTO Student1
(`id`,`status`,`amount`, `Name`, `date`)
VALUES
(1,0,4500, 'ram', '04/02/2012'),
(2,0,2000, 'shyam', '05/09/2013'),
(4,0,1500, 'ghanshyam', '08/11/2014')
;
CREATE TABLE Student2
(`id` int,`status` int,`amount` int , `Name` varchar(10), `date` varchar(55))
;
INSERT INTO Student2
(`id`,`status`,`amount`, `Name`, `date`)
VALUES
(3,0,4500, 'gopal', '04/02/2012'),
(2,0,8000, 'radheshyam', '15/11/2013'),
(4,1,1500, 'ghanshyam', '18/10/2015')
;
CREATE TABLE Student3
(`id` int,`status` int,`amount` int , `Name` varchar(10), `date` varchar(55))
;
INSERT INTO Student3
(`id`,`status`,`amount`, `Name`, `date`)
VALUES
(1,1,4500, 'ram', '14/02/2012'),
(2,0,6500, 'radhe', '11/11/2014'),
(3,1,4500, 'gopal', '14/02/2015')
;
Excepted Result :
id status amount Name date
2 0 2000 shyam 05/09/2013
2 0 6500 radhe 11/11/2014
2 0 8000 radheshyam 15/11/2013
You just use union all to bring the tables together. One way is:
select s.*
from (select s.* from student1 s union all
select s.* from student2 s union all
select s.* from student3 s
) s
where id = 2;
As I say in the comment, though, normally you would have three tables rather than one.
I realize that I might have misunderstood the question. If you want to find records that have the same id but different names, then use:
select s.id, group_concat(s.name) as names
from (select s.* from student1 s union all
select s.* from student2 s union all
select s.* from student3 s
) s
group by s.id
having count(distinct name) = 3 -- or perhaps >= 2, depending on what you mean
If you want the full records, you can join this back to the original tables.
EDIT:
If you want all the original rows:
select s.*
from (select s.id, group_concat(s.name) as names
from (select s.* from student1 s union all
select s.* from student2 s union all
select s.* from student3 s
) s
group by s.id
having count(distinct name) = 3
) ss join
(select s.* from student1 s union all
select s.* from student2 s union all
select s.* from student3 s
) s
on ss.id = s.id;
I want to calculate percentage of three different grades A,B,C
1 product have A grade
5 products have B grade
3 products gave C grade
SQL - This Query return 3 rows
SELECT count(*) FROM table1 WHERE pid = '480' AND grade IN
( SELECT DISTINCT grade FROM table1 )
GROUP BY grade
------------------------
CCA_ST2 count(*)
------------------------
A 1
B 5
C 3
------------------------
How can i calculate percentages ?
( SELECT count(*) FROM table1 WHERE pid = '480' AND grade IN
( SELECT DISTINCT grade FROM table1 )
GROUP BY grade
)
DIVIDE BY
( SELECT COUNT(*) FROM table1 WHERE pid = '480' ) * 100
I tried with this query
SELECT grade,
( SELECT count(*) FROM table1 WHERE pid = '480' AND grade IN
( SELECT DISTINCT grade FROM table1 )
GROUP BY grade
)
/
( SELECT count(*) FROM table1 WHERE pid = '480' )
* 100
AS score
FROM table1 GROUP BY grade
I got this error . How can i solve this
subquery returns more than one row
i don't really want to create procedure for this , i know this can be done by query . But i'm feeling so lazy today.
You can't take the count from all groups and divide them by the total count, you have to divide each count by the total count:
SELECT
grade,
100 * count(*) / (SELECT count(*) FROM table1 WHERE pid = '480') AS score
FROM table1
WHERE pid = '480'
GROUP BY grade
ORDER BY grade
person_id | manager_id | name |
| | |
-------------------------------
Query to find name of manager who supervises maximum number of employees?
Added: This is the only table. Yes self-referencing. DB is mysql. Recursive queries will also do.
This query returns the manager_id and manager_name of the manager with the maximal number of employees.
The trick is in the HAVING clause, which allows aggregates and counts over multiple rows.
SELECT manager_id,name, count(*)
FROM table
GROUP BY manager_id, name
HAVING max(count(*));
You can read more in the short but informative w3schools.com HAVING clause tutorial.
If the manager_id references a person id in the same table, Svinto's answer might be more suitable.
SELECT name
FROM table
WHERE person_id = (
SELECT manager_id
FROM table
GROUP BY manager_id
HAVING max(count(*)))
It's not entirely clear to me what you want, so if this isn't what you want please clarify your question.
This query returns just one of the managers if there is a tie:
SELECT T2.name FROM (
SELECT manager_id
FROM table1
WHERE manager_id IS NOT NULL
GROUP BY manager_id
ORDER BY count(*) DESC
LIMIT 1
) AS T1
JOIN table1 AS T2
ON T1.manager_id = T2.person_id
Result of query:
Bar
Here's a query that fetches all managers with the tied maximum count in the case that there is a tie:
SELECT name FROM (
SELECT manager_id, COUNT(*) AS C
FROM person
WHERE manager_id IS NOT NULL
GROUP BY manager_id) AS Counts
JOIN (
SELECT COUNT(*) AS C
FROM person
WHERE manager_id IS NOT NULL
GROUP BY manager_id
ORDER BY COUNT(*) DESC
LIMIT 1
) AS MaxCount
ON Counts.C = MaxCount.C
JOIN person
ON Counts.manager_id = person.person_id
Result of the second query:
Foo
Bar
Here's my test data:
CREATE TABLE Table1 (person_id int NOT NULL, manager_id nvarchar(100) NULL, name nvarchar(100) NOT NULL);
INSERT INTO Table1 (person_id, manager_id, name) VALUES
(1, NULL, 'Foo'),
(2, '1', 'Bar'),
(3, '1', 'Baz'),
(4, '2', 'Qux'),
(5, '2', 'Quux'),
(6, '3', 'Corge');
Assuming manager_id have a reference to person_id and name of table: table_name
SELECT name FROM (
SELECT manager_id
FROM table_name
GROUP BY manager_id
ORDER BY COUNT(*) DESC
LIMIT 1
) t
INNER JOIN table_name ON t.manager_id = table_name.person_id
edit:
Removed HAVING MAX COUNT, added ORDER BY COUNT DESC LIMIT 1 in subquery