Selection of rows providing a specific condition in sql - sql

I want to create a query like this:
For student_name, if the number of grade=0 and grade=1 students is equal, let's not select this person, but if the number of grade=0 and grade=1 students is different, let's select this person. In the query I will use for my example, Jack will not be selected, everyone else will be selected.
CREATE TABLE student
(
student_name VARCHAR(50),
grade CHAR(1)
)
INSERT INTO student
SELECT 'Jack', '0' UNION ALL
SELECT 'Jack', '0' UNION ALL
SELECT 'Jack', '0' UNION ALL
SELECT 'Jack', '1' UNION ALL
SELECT 'Jack', '1' UNION ALL
SELECT 'Jack', '1' UNION ALL
SELECT 'Rose', '0' UNION ALL
SELECT 'Rose', '0' UNION ALL
SELECT 'John', '1' UNION ALL
SELECT 'John', '1' UNION ALL
SELECT 'John', '1' UNION ALL
SELECT 'John', '1' UNION ALL
SELECT 'Dave', '1' UNION ALL
SELECT 'Dave', '1' UNION ALL
SELECT 'Chris', '0'
select * from student

Use aggregation and set the condition in the HAVING clause:
SELECT student_name
FROM student
GROUP BY student_name
HAVING COUNT(CASE WHEN grade = '0' THEN 1 END) <> COUNT(CASE WHEN grade = '1' THEN 1 END);
See the demo.

Related

How to resolve missing SELECT keyword error when trying to insert select

It doesn't matter how I write this statement, I always get the ORA-00928 missing select keyword error.
I'm trying to insert values from a query into a table. The result of the query has the same amount of columns as the table where it needs to be inserted to. I have tried making it as an CTE. Even a select-query from an existing table returns the same error.
Code is like:
WITH FIRST_CTE(FrstCol1,FrstCol2)
AS
(
SELECT 't', '1' from dual UNION ALL
SELECT 's', '2' from dual
)
,
SECOND_CTE(SndCol1,SndCol2)
AS
(
SELECT 't', '3' from dual UNION ALL
SELECT 'z', '4' from dual
)
INSERT INTO TABLE_1
SELECT *
from
(SELECT * FROM FIRST_CTE) A
JOIN
(SELECT * FROM SECOND_CTE) B
ON A.FrstCol1 = B.SndCol1
;
Any suggestions?
No problem occurs if you put INSERT part to the beginning, since SELECT statement starts by WITH clause ( for this case )
INSERT INTO TABLE_1
WITH FIRST_CTE(FrstCol1,FrstCol2)
AS
(
SELECT 't', '1' from dual UNION ALL
SELECT 's', '2' from dual
)
,
SECOND_CTE(SndCol1,SndCol2)
AS
(
SELECT 't', '3' from dual UNION ALL
SELECT 'z', '4' from dual
)
SELECT *
from
(SELECT * FROM FIRST_CTE) A
JOIN
(SELECT * FROM SECOND_CTE) B
ON A.FrstCol1 = B.SndCol1;
provided that TABLE_1 is such a table that is created as
create table TABLE_1(FrstCol1 varchar2(100),FrstCol2 varchar2(100),
SndCol1 varchar2(100), SndCol2 varchar2(100))

Insert Into command just works for one Value not for more values because of comma placement

Tried to fill in a table with insert into command, but it just works for one value not for more.
I work with MS Access and the mistake is the comma placement, but I didn't find the mistake. Tried it with just one value and that works, but I have to insert it all.
INSERT INTO Abteilung (ID, Abteilung, Mitarbeiteranzahl)
VALUES (('1', 'Einkauf', '5'), ('2', 'HR', '5'), ('3', 'Controlling', '5'),
('4', 'Produktion', '20'), ('5', 'Vertrieb', '20'),
('6', 'Qualitätsmanagement', '3'), ('7', 'Industrial Engineering', '8')
)
You can't do this as easily in access as other major db but it can be made possible. First off, create yourself a table with one row:
CREATE TABLE dual([Dummy] Integer)
INSERT INTO dual VALUES(1)
Now you can select a bunch of hard coded values "from" this table:
INSERT INTO Abteilung
(
ID,
Abteilung,
Mitarbeiteranzahl
)
SELECT '1' as e1,'Einkauf' as e2, '5' as e3 FROM dual
UNION
SELECT '2','HR','5' FROM dual
UNION
SELECT '3','Controlling','5' FROM dual
UNION
SELECT '4','Produktion','20' FROM dual
UNION
SELECT '5','Vertrieb','20' FROM dual
UNION
SELECT '6','Qulaitätsmanagement','3' FROM dual
UNION
SELECT '7','Industrial Engineering','8' FROM dual
You might need to wrap all those selects in another SELECT * FROM, I can't quite remember
By the time you're done writing all those out you might well get to thinking it would be as easy to just write N number of insert statements..
There is a way how you can insert rows without building SQL strings.
check this Answer
You can't insert more than 1 row with an INSERT statement in Access.
Even multiple INSERT statements separated with ; are not allowed.
You can use a trick though like this:
INSERT INTO Abteilung ( ID, Abteilung, Mitarbeiteranzahl)
SELECT * FROM (
SELECT '1' AS ID, 'Einkauf' AS Abteilung, '5' AS Mitarbeiteranzahl FROM (SELECT COUNT(*) FROM Abteilung)
UNION ALL
SELECT '2','HR','5' FROM (SELECT COUNT(*) FROM Abteilung)
UNION ALL
SELECT '3','Controlling','5' FROM (SELECT COUNT(*) FROM Abteilung)
UNION ALL
SELECT '4','Produktion','20' FROM (SELECT COUNT(*) FROM Abteilung)
UNION ALL
SELECT '5','Vertrieb','20' FROM (SELECT COUNT(*) FROM Abteilung)
UNION ALL
SELECT '6','Qulaitätsmanagement','3' FROM (SELECT COUNT(*) FROM Abteilung)
UNION ALL
SELECT '7','Industrial Engineering','8' FROM (SELECT COUNT(*) FROM Abteilung)
)
Unfortunately the FROM clause is needed for each of the INSERTs and it must return only 1 row, this is why I used SELECT COUNT(*) which for a large table may be not that efficient.
Can you try the following query:
INSERT INTO Abteilung
(
ID,
Abteilung,
Mitarbeiteranzahl
)
SELECT '1','Einkauf','5'
UNION ALL SELECT '2','HR','5'
UNION ALL SELECT '3','Controlling','5'
UNION ALL SELECT '4','Produktion','20'
UNION ALL SELECT '5','Vertrieb','20'
UNION ALL SELECT '6','Qulaitätsmanagement','3'
UNION ALL SELECT '7','Industrial Engineering','8'
Hope this should work.

COUNT & PRINT matched Row values in NEW COLUMNS

I am trying to make the column name from row value and count the total value of each row name to show into the particular column name. Result will show from 30 days.
SELECT id
, Name
, Designation
, DeptName
, Sts
, COUNT(Sts) as 'COUNT'
FROM table
WHERE Date >= DATEADD(month,-1,GETDATE())
AND Name = 'Neo'
GROUP BY id, Name, Designation, DeptName, Sts
ORDER id
Here is my output
Required Output is...
use conditional aggregation
SELECT id
, Name
, Designation
, DeptName
, sum (case when Sts='H' then 1 end) H
,sum (case when Sts='A' then 1 end) A
,sum (case when Sts='P' then 1 end) P
FROM table
WHERE Date >= DATEADD(month,-1,GETDATE())
AND Name = 'Neo'
GROUP BY id, Name, Designation, DeptName
ORDER id
The CASE statement goes through conditions and return a value when the first condition is met (like an IF-THEN-ELSE statement) and when a condition will meet it will sum up for that particular value
As eariler suggested, use pivot
WITH temp AS(
SELECT 1 AS id,'Neo' AS name,'Zonal Manager' AS designation, 'Admin' AS deptname, 'H' AS sts ,2 AS cnt FROM dual UNION ALL
SELECT 1,'Neo','Zonal Manager', 'Admin', 'A',3 FROM dual UNION ALL
SELECT 1,'Neo','Zonal Manager', 'Admin', 'P',4 FROM dual UNION ALL
SELECT 1,'Neo','Zonal Manager', 'Admin', 'A',1 FROM dual UNION ALL
SELECT 1,'Neo','Zonal Manager', 'Admin', 'A',8 FROM dual )
SELECT p.*
FROM temp
PIVOT(
SUM(cnt)
FOR sts
IN ('A', 'P', 'H')
) p

SQL - select students that had exams on every subject

I have two tables:
Exams(StudentID, SubjectID),
Subjects(SubjectID)
And want to select students that had exam on all subjects. How to do it?
Is it possible without using GROUP and COUNT?
You can do it in many ways. One of those:
DECLARE #students TABLE ( id INT )
DECLARE #exams TABLE ( id INT )
DECLARE #studentexams TABLE
(
studentid INT ,
examid INT
)
INSERT INTO #exams
VALUES ( 1 ),
( 2 )
INSERT INTO #students
VALUES ( 1 ),
( 2 ),
( 3 )
INSERT INTO #studentexams
VALUES ( 1, 1 ),
( 1, 2 ),
( 2, 1 )
SELECT *
FROM #students s
WHERE NOT EXISTS ( SELECT *
FROM #exams e
WHERE e.id NOT IN ( SELECT se.examid
FROM #studentexams se
WHERE se.studentid = s.id ) )
Output:
id
1
Is this what you're after:
--list all students
select *
from #students st
--where there isn't
where not exists
(
--any subject
select top 1 1
from #subjects su
--for which that student did not take an exam
where su.id not in
(
select subjectid
from #exams e
where studentId = st.id
)
)
Here's the full code (i.e. including sample data tables):
declare #subjects table(id bigint not null identity(1,1), title nvarchar(32))
declare #students table(id bigint not null identity(1,1), name nvarchar(32))
declare #exams table(id bigint not null identity(1,1), studentId bigint, subjectId bigint, grade nchar(1), attempt int)
insert #subjects select 'Maths' union select 'English' union select 'Geography' union select 'Computer Science'
insert #students select 'Anna' union select 'Billy' union select 'Christie' union select 'Daniel'
insert #exams select st.Id, su.Id, grade, attempt
from
(
select 'Anna' student, 'Maths' subject, 'A' grade, 1 attempt
union select 'Anna' student, 'English' subject, 'A' grade, 1 attempt
union select 'Anna' student, 'Geography' subject, 'A' grade, 1 attempt
union select 'Anna' student, 'Computer Science' subject, 'A' grade, 1 attempt
union select 'Billy' student, 'Maths' subject, 'A' grade, 1 attempt
union select 'Billy' student, 'Computer Science' subject, 'A' grade, 1 attempt
union select 'Christie' student, 'Maths' subject, 'A' grade, 1 attempt
union select 'Christie' student, 'English' subject, 'F' grade, 1 attempt
union select 'Christie' student, 'English' subject, 'E' grade, 2 attempt
union select 'Christie' student, 'English' subject, 'A' grade, 3 attempt
union select 'Daniel' student, 'Maths' subject, 'A' grade, 1 attempt
union select 'Daniel' student, 'English' subject, 'A' grade, 1 attempt
union select 'Daniel' student, 'Geography' subject, 'A' grade, 1 attempt
union select 'Daniel' student, 'Computer Science' subject, 'F' grade, 1 attempt
union select 'Daniel' student, 'Computer Science' subject, 'A' grade, 2 attempt
) x
inner join #students st on st.name = x.student
inner join #subjects su on su.title = x.subject
--list all students
select *
from #students st
--where there isn't
where not exists
(
--any subject
select top 1 1
from #subjects su
--for which that student did not take an exam
where su.id not in
(
select subjectid
from #exams e
where studentId = st.id
)
)

Why do I still get duplicates on [CONMAT_MATCHING_DONOR] even after using DISTINCT?

I still get duplicates on [CONMAT_MATCHING_DONOR] even after using DISTINCT.
SELECT TOP 1000 [CONTRIB_MATCH_ID]
,[CONMAT_CONTRIBUTION]
,[CONMAT_FORM_RECEIVED_DATE]
,[CONMAT_MATCHING_DONOR]
,[CONMAT_STATUS]
,[STATUS_DESC]
,[CONMAT_STATUS_DATE]
FROM [ods_production].[dbo].[SPT_CONTRIB_MATCH]
WHERE [CONMAT_MATCHING_DONOR] IN (SELECT DISTINCT
[CONMAT_MATCHING_DONOR]
FROM [ods_production].[dbo].[SPT_CONTRIB_MATCH])
ORDER BY [CONMAT_MATCHING_DONOR] DESC
Your usage of DISTINCT in the IN clause doesn't make much sense - this will not affect the results of your query in any way.
Consider:
WITH v_base(name) AS (
SELECT 'A' UNION ALL
SELECT 'A' UNION ALL
SELECT 'B')
SELECT name FROM v_base WHERE name IN (SELECT DISTINCT name from v_base)
which more or less translates to
WITH v_base(name) AS (
SELECT 'A' UNION ALL
SELECT 'A' UNION ALL
SELECT 'B')
SELECT name FROM v_base WHERE name IN ('A', 'B')
vs
WITH v_base(name) AS (
SELECT 'A' UNION ALL
SELECT 'A' UNION ALL
SELECT 'B')
SELECT DISTINCT name FROM v_base WHERE name IN (SELECT name from v_base)
which translates to
WITH v_base(name) AS (
SELECT 'A' UNION ALL
SELECT 'A' UNION ALL
SELECT 'B')
SELECT DISTINCT name FROM v_base WHERE name IN ('A', 'A', 'B')
and the difference should become clear.
SQL Fiddle