sql - find max value - sql

I have a table with 3 columns: Code, Year, percentage.
I need to return the code with the lowest (minimal) percentage in 2009. After this, I want also the name of the code, that exsist in other table that I made.
I only think using CREATE VIEW, but I prefer not to do so.

Select table.code, table.year, table.percentage, othertable.name
from table
inner join othertable on table.FKId = othertable.PKid
where year = 2009
and percentage =
(select min(percentage)
from table
where year = 2009)
Updated to include the othertable... since we don't have names.
UPDATED
Now that we have table names... Updated 3rd time now that I know year is string.
Select E.Code, C.Name
From dbo.Exam E
inner join dbo.Course C
ON E.Code = C.Code
Where E.Year = '2009' and --<-- PROBLEM LIKELY HERE year was string not int.
E.Fail = (select MIN(E2.Fail)
from dbo.Exam E2 where E2.Year = '2009') --<--Don't forget here too.
From comments: sample Data:
INSERT INTO Exam VALUES(333,'2009',40)
INSERT INTO Exam VALUES(333,'2009',20)
INSERT INTO Exam VALUES(555,'2009',19)
INSERT INTO Exam VALUES(444,'2009',19)
INSERT INTO Exam VALUES(777,'2009',23)
INSERT INTO Exam VALUES(333,'2009',0)
INSERT INTO Course VALUES(111,'Name1',5)
INSERT INTO Course VALUES(333,'Name2',5)
INSERT INTO Course VALUES(444,'Name3',6)
INSERT INTO Course VALUES(555,'Name4',3)
INSERT INTO Course VALUES(777,'Name5',3)
INSERT INTO Course VALUES(999,'Name6',6)
Assumption is result should be
Name2, 5

You can use a group by to find the lowest percentage for a year, and then join back to the main tables to find the corresponding other columns:
select *
from CodeYearPercTbl cyp
join CodeTbl c
on c.Code = cyp.Code
join (
select Year
, min(Percentage) as MinPerc
from CodeYearPercTbl
group by
Year
) as filter
on filter.Year = cyp.Year
and filter.MinPerc = cyp.Percentage
where cyp.Year = 2009

Table-1 : Code,Year,Percentage
Table-2 : Code,CodeName
select T1.Code,T2.CodeName,T1.Percentage from
(
select TOP 1 Code,Percentage
from Table-1
where Year = '2009'
order by Percentage asc
) T1 inner join Table-2 T2 on T1.Code = T2.Code

Try this:
select a.Code, c.Name
from YourTable a inner join AnotherTable c on a.Code = c.Code
where a.Percentage = (select MIN(Percentage)
from YourTable b where b.Year = '2009'
)

Related

SQL query - Return 0 for the column if no record found

I will like to see the specific fields returns with 0 value when there is no record found.
Below are my SQL queries that I have tried so far.
SELECT Customer, Address, Number of lines, Date
FROM table_name
WHERE Date = '30-5-2022' AND Customer IN (A, B, C)
What it returns is only 1 row as below.
Customer
Address
Number of Lines
Date
A
3
RF
30-5-2022
But what I expected to see is:
Customer
Address
Number of Lines
Date
A
UK
33
30-5-2022
B
0
0
30-5-2022
C
0
0
30-5-2022
The customer B and C has no record on 30-5-2022 but I will still need to see the rows but certain columns can be 0.
Please advise if anything that I have missed out? Thanks a lot!
Try below query:
SELECT A.Customer, ISNULL(B.Address, 0),
ISNULL(B.[Number of lines],0), ISNULL(B.Date, '30-05-2022') Date
FROM
(
SELECT DISTINCT Customer
FROM table_name
) A
LEFT JOIN table_name B
ON A.Customer = B.Customer
AND B.Date = '30-5-2022'
This will output all the customers present in the table. You can filter the customers with WHERE clause in the end of the above query based on your requirement.
dbfiddle Link
Assuming customers are in one table (cust) and other stuff in another table (table_name) and they are connected with an id called custid, you need some sweet, sweet left join action, such as:
SELECT c.Customer, c.Address, isnull([Number of lines],0), d.Date
FROM cust c left join table_name d on c.custid = d.custid and
d.Date = '30-5-2022' where
c.Customer IN ('A', 'B', 'C')
You need to put A, B, C in a table and left-join the main table to it. All other conditions must then go in the ON clause not the WHERE.
You can use a virtual VALUES clause for this
SELECT Customer, Address, Number of lines, Date
FROM (VALUES
('A'),
('B'),
('C')
) v(Customer)
LEFT JOIN table_name tn ON tn.Customer = v.Customer
AND tn.Date = '30-5-2022';
Alternatively you can pass in a Table Valued Parameter, or use a table variable. Don't forget to add a primary key.
DECLARE #tmp TABLE (Customer varchar(100) PRIMARY KEY);
INSERT #tmp(Customer) VALUES
('A'),
('B'),
('C');
SELECT Customer, Address, Number of lines, Date
FROM #tmp v
LEFT JOIN table_name tn ON tn.Customer = v.Customer
AND tn.Date = '30-5-2022';

SQL for 2 tables

I have these 2 tables:
Table A
Country State
-----------------
US OH
US FL
US WA
Table B
State LastVisitDate City
----------------------------------
OH 15/10/2019 Bedford
FL 10/12/2019 Bell
WA 20/09/2019 Perth
Table A can be linked with table B by field "State".
What would be the query to get the latest (last visit date) in country=US, doesn't matter which state, e.g.:
US,10-12-2019,FL,Bell
I tried inner join but couldn't make it work.
Always try to explain your question with sample data and query you tried for.
Here is query with some sample data:
CREATE TABLE A
(
COUNTRY VARCHAR(10),
State VARCHAR(10)
);
INSERT INTO A VALUES('US','OH'),
('US','FL'),
('AU','WA');
CREATE TABLE B
(
State VARCHAR(10),
LastVisitDate DATE,
City VARCHAR(20)
);
INSERT INTO B VALUES
('OH','2019-10-15','Bedford'),
('FL','2019-12-10','Bell'),
('WA','2019-09-20','Perth');
Expected Result:
US,10-12-2019,FL,Bell
Query:
SELECT a.COUNTRY,b.LastVisitDate,b.State,b.City
FROM A
INNER JOIN B ON a.State = b.State
WHERE a.COUNTRY = 'US'
ORDER BY b.LastVisitDate DESC
Limit 1;
SQL Fiddle
Before you try below code you must be reformat last visited date table structure like YYYY/MM/DD in SQL Table and you must replace actual tables name and columns name in below query.
SELECT MAX(table_b.last_visited_date) AS last_visited_date
FROM table_a
INNER JOIN table_b
ON table_a.state = table_b.state WHERE table_a.country = 'US' Limit 1;
Try this below script-
Note: As Tanmay said, you need to reformat your date values to get the correct output.
DEMO HERE
SELECT N.country,
N.mx_date LastVisitDate,
B.City,
B.State
FROM
(
SELECT Country,MAX(LastVisitDate) mx_date
FROM Table_A A
INNER JOIN Table_B B ON A.State = B.State
GROUP BY Country
)N
INNER JOIN Table_A A ON A.Country = N.Country
INNER JOIN Table_B B ON A.State = B.State
WHERE N.mx_date = B.LastVisitDate
SELECT top 1(country,
last_visit_date)
FROM A
JOIN B ON A.State = B.State
WHERE A.Country ="Country Name"
ORDER BY B.Last_visit_Date DESC

How to search for a list of combinations of two columns in a table?

I have a list of combinations from a table (First_Name and Start month of employment).
I need to be able to search the table and determine what entries in the table are not in the list. Ex. (Mark, January exists but Mark, March doesn't.)
Is there a shorter way to do this than append every combination to the SQL? This is a pretty long list out of a pretty large table.
You can CROSS JOIN employee names with list of months to create all possible combinations. LEFT JOIN for the rest:
SELECT
FROM (
SELECT DISTINCT First_Name FROM t
) AS emp
CROSS JOIN (VALUES
('January'), ('February'), ('March'), ('April'), ('May'), ('June'),
('July'), ('August'), ('September'), ('October'), ('November'), ('December')
) mon(Month_Name)
LEFT JOIN t ON emp.First_Name = t.First_Name AND mon.Month_Name = t.Month_Name
WHERE t.PK IS NULL
Use joins to a temporal table or equivalent expressions. Something like
SELECT t.*
FROM ( SELECT 'Mike' AS name, 'March' AS month
UNION SELECT 'John' AS name, 'April' AS month) AS aux
JOIN table t ON t.name = aux.name
AND t.month = aux.name
Of course it can be a literal temporary or standard table if you alredy have the data.
You need a left join or not exists for this. For instance:
select v.*
from (values ('Mark', 'January'), ('Mark', 'March')) v(name, mon)
where not exists (select 1
from t
where t.name = v.name and t.mon = v.mon
);

SQL INNER JOIN issue when value as 0

I have shortened my query & posted only relevant parts. There are many INNER JOINS. Here is the query :-
DECLARE
#startdate DATE = '2018-05-01',
#enddate DATE = '2018-05-05';
WITH calendar
AS (SELECT #startdate AS Dates
UNION ALL
SELECT Dateadd(dd, 1, Dates)
FROM calendar
WHERE Dates < #enddate)
SELECT emp.Code, cv1.CategoryName AS Category FROM (
SELECT *
FROM calendar c
CROSS JOIN (SELECT DISTINCT Id
FROM [dbo].[Employee] where CompanyId = 1) E
WHERE NOT EXISTS (SELECT 1
FROM [dbo].[ShiftSchedule] t
WHERE c.Dates = t.ShiftDate
AND E.Id = t.EmployeeId AND CompanyId = 11)) AS c
INNER JOIN [dbo].[Employee] emp
ON c.Id = emp.Id
INNER JOIN [dbo].[Category] cv1
ON cv1.id = emp.Category
AND emp.Id IN ( 400 )
OPTION (maxrecursion 0)
The problem here is in the INNER JOIN of [dbo].[Category].
In very rare cases - Category is found 0 in Employee Table. So what I want is if Category is 0 then also that record should be included in Result Set. Currently it skips the Records with 0.
Can this be achieved in the above query?
Example :- In Employee table I have an employee Steve & in Category
Column Value is 0. And in Category Table in column Id, there is no
record with 0. So this Employee Steve is not coming in result set.
Basically, you're simply asking for your employee to be returned even when it cannot be matched to a category. That's easy: that's what a LEFT JOIN is for. There's no reason to treat 0 as special here: based on your description, it seems to me as if you'd want the same for any other values that don't exist as category IDs, it's just that there are no such other values.

Help with query

I'm trying to make a query that looks at a single table to see if a student is in a team called CMHT and in a medic team - if they are I don't want to see the result.
I only want see the record if they're only in CMHT or medic, not both.
Would the right direction be using sub query to filter it out? I've done a search on NOT IN but how could you get to see check if its in more then 2 teams are not?
Student Team ref
1 CMHT 1
1 Medic 2
2 Medic 3 this would be in the result
3 CMHT 5 this would be in the result
So far I've done the following code would I need use a sub query or do a self join and filter it that way?
SELECT Table1.Student, Table1.Team, Table1.refnumber
FROM Table1
WHERE (((Table1.Team) In ('Medics','CMHT'))
This is Mark Byers's answer with a HAVING clause instead of a subquery:
SELECT Student, Team, ref
FROM Table1
GROUP BY Student
HAVING COUNT(Student) = 1
SELECT *
FROM students
WHERE NOT EXISTS
(
SELECT NULL
FROM students si
WHERE si.student = s.student
AND si.team = 'CMHT'
)
OR NOT EXISTS
(
SELECT NULL
FROM students si
WHERE si.student = s.student
AND si.team = 'Medic'
)
SELECT a.*
FROM Table1 a
INNER JOIN
( SELECT Student, COUNT(*) FROM Table1
GROUP BY Student
HAVING COUNT(*) = 1)b
ON (a.Student = b.Student)
how could you get to see check if its in 2 or more teams?
You can count the number of teams per student and then filter only those you want to see:
SELECT student FROM
(
SELECT student, COUNT(*) AS cnt
FROM Table1
GROUP BY student
) T1
WHERE cnt = 1
You can do it with outer join
select COALESCE(t1.Student, t2.Student) as Student,
COALESCE(t1.Team, t2.Team) as Team,
COALESCE(t1.ref, t2.ref) as ref
from
(select * from Student where Team = 'CMHT') t1
outer join
(select * from Student where Team = 'Medic') t2
on t1.Student = t2.Student
where
t1.Student is null or
t2.Student is null;