calculating sum from another table using SQL - sql

I have a table (District) have columns (Id - District name) . And another table (delivery) have columns (quantity - district Id). can i have a result like a table with every district name in a column and sum of quantity in other column using sql?

I understand that this question will be closed as this site is not about doing homework
select a.district_name, b.total
from District as a
inner join
(
select district_id, sum(quantity) as total
from delivery
group by district_id
) as b
on a.id = b.district_id

Try below code
SELECT dis.district_name,SUM(del.quantity) as quantity
FROM district as dis
INNER JOIN delivery as del
ON dis.id = del.district_id
GROUP BY del.district_id

you can use this code:
SELECT ID, Name, SUM(Quantity) AS SumOfQuantity
FROM
(
SELECT District.ID, District.Name, Delivery.Quantity
FROM District, Delivery
WHERE District.Id = Delivery.DistrictID
) AS T1
GROUP BY ID, Name

Related

Select columns with multiple purcahses in a given date

table structure
I need to get names (FIO) of all the people that purchased product a and product b in any given day (but must be 2 purchases in a day) in april, or any other specified month.
What I tried to do is
with
purchased_items as
(
select customer_key
from purchase p
join product pr
on p.product_key = pr.product_key
where pr.name in ('Teddy bear', 'LEGO')
AND p.date_sold BETWEEN '01.04.2019' AND '30.04.2019'
group by customer_key
having count(distinct p.product_key) = 2
)
select *
from customer c
where exists (
select *
from purchased_items pui
where c.customer_key = pui.customer_key
);
But that only gives clients that bought 2 items in a month (not a single day).
I also suspect that it can be done by querying for Date, Client_name (FIO), array_agg(product.Name /*group by date */ ) , but I am not sure how to implemet it.
Thank you in advance for any help !
EDIT: figured it out.
with a as (
SELECT c.FIO, p.date_sold, pr.Name
FROM customer c
JOIN purchase p ON c.customer_key = p.customer_key
JOIN product pr ON p.product_key = pr.product_key
Where p.date_sold BETWEEN '01.04.2019' AND '30.04.2019' and (pr.name like '%LEGO%' OR pr.name like '%Teddy bear%') ),
count_name as (
select fio, count(distinct Name) as count, date_sold
from a
group by date_sold, fio)
select DISTINCT FIO
from count_name
where count=2
Although it's probably very subotimal

SQL - Select highest value when data across 3 tables

I have 3 tables:
Person (with a column PersonKey)
Telephone (with columns Tel_NumberKey, Tel_Number, Tel_NumberType e.g. 1=home, 2=mobile)
xref_Person+Telephone (columns PersonKey, Tel_NumberKey, CreatedDate, ModifiedDate)
I'm looking to get the most recent (e.g. the highest Tel_NumberKey) from the xref_Person+Telephone for each Person and use that Tel_NumberKey to get the actual Tel_Number from the Telephone table.
The problem I am having is that I keep getting duplicates for the same Tel_NumberKey. I also need to be sure I get both the home and mobile from the Telephone table, which I've been looking to do via 2 individual joins for each Tel_NumberType - again getting duplicates.
Been trying the following but to no avail:
-- For HOME
SELECT
p.PersonKey, pn.Phone_Number, pn.Tel_NumberKey
FROM
Persons AS p
INNER JOIN
xref_Person+Telephone AS x ON p.PersonKey = x.PersonKey
INNER JOIN
Telephone AS pn ON x.Tel_NumberKey = pn.Tel_NumberKey
WHERE
pn.Tel_NumberType = 1 -- e.g. Home phone number
AND pn.Tel_NumberKey = (SELECT MAX(pn1.Tel_NumberKey) AS Tel_NumberKey
FROM Person AS p1
INNER JOIN xref_Person+Telephone AS x1 ON p1.PersonKey = x1.PersonKey
INNER JOIN Telephone AS pn1 ON x1.Tel_NumberKey = pn1.Tel_NumberKey
WHERE pn1.Tel_NumberType = 1
AND p1.PersonKey = p.PersonKey
AND pn1.Tel_Number = pn.Tel_Number)
ORDER BY
p.PersonKey
And have been looking over the following links but again keep getting duplicates.
SQL select max(date) and corresponding value
How can I SELECT rows with MAX(Column value), DISTINCT by another column in SQL?
SQL Server: SELECT only the rows with MAX(DATE)
Am sure this must be possible but been at this a couple of days and can't believe its that difficult to get the most recent / highest value when referencing 3 tables. Any help greatly appreciated.
select *
from
( SELECT p.PersonKey, pn.Phone_Number, pn.Tel_NumberKey
, row_number() over (partition by p.PersonKey, pn.Phone_Number order by pn.Tel_NumberKey desc) rn
FROM
Persons AS p
INNER JOIN
xref_Person+Telephone AS x ON p.PersonKey = x.PersonKey
INNER JOIN
Telephone AS pn ON x.Tel_NumberKey = pn.Tel_NumberKey
WHERE
pn.Tel_NumberType = 1
) tt
where tt.rn = 1
ORDER BY
tt.PersonKey
you have to use max() function and then you have to order by rownum in descending order like.
select f.empno
from(select max(empno) empno from emp e
group by rownum)f
order by rownum desc
It will give you all employees having highest employee number to lowest employee number. Now implement it with your case then let me know.

take each maximum value of a column and get information from another table

i have two tables:
create table saller(
id_saller int IDENTITY PRIMARY KEY,
name varchar(50),
branch varchar(10)
);
create table sale(
id_sale int IDENTITY PRIMARY KEY,
amount float,
id_saller int,
CONSTRAINT fk_saller FOREIGN KEY (id_saller)REFERENCES saller(id_saller)
);
i wanna get the biggest selling value of the amount for each branch
and get the name and id of the saller in charge for the biggest selling
i tried this:
SELECT saller.name, saller.id_saller,maxv.branch, maxv.maxbranch
FROM saller
INNER JOIN sale
ON saller.id_saller = sale.id_saller
INNER JOIN (
SELECT saller.branch,saller.id_saller,MAX(sale.amount) AS maxbranch
FROM saller
INNER JOIN sale
ON saller.id_saller = sale.id_saller
GROUP BY saller.branch,saller.id_saller
) AS maxv ON(sale.id_saller = maxv.id_saller)
One way to do it if you want to return exactly one row per branch even if you have ties
SELECT branch, id_saller, name, amount
FROM
(
SELECT r.branch, s.id_saller, r.name, s.amount,
ROW_NUMBER() OVER (PARTITION BY r.branch ORDER BY s.amount DESC) rnum
FROM sale s JOIN saller r
ON s.id_saller = r.id_saller
) q
WHERE q.rnum = 1
or if you want the highest value with ties
SELECT branch, id_saller, name, amount
FROM
(
SELECT r.branch, s.id_saller, r.name, s.amount,
RANK() OVER (PARTITION BY r.branch ORDER BY s.amount DESC) rank
FROM sale s JOIN saller r
ON s.id_saller = r.id_saller
) q
WHERE q.rank = 1
Here is SQLFiddle demo
According to your question, I don't understand the presence of branch, maybe a table that has not been mentionned. But to retrieve the seller id and name, you can try this;
SELECT saller.name, saller.id_saller
FROM saller
INNER JOIN sale
ON saller.id_saller = sale.id_saller
WHERE sale.Amount = (Select Max(Amount) from sale)

sql - find max value

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'
)

SQL Multiple Duplicate Row Detection

I'm trying to determine a correct way to isolate rows within a table that have the same values in 2 columns.
There are two tables, one (Name) with the person's names and IDs, and the other one (Nation) with people's IDs and their nations. I join the two tables with inner join, and now the new table columns consist of an ID, first name, last name, and nation. If I want to find pairs of people who have the same last name and are from the same nation, why isn't
select ID, FName, LName, Nation
from (Name inner join Nation on Name.ID = Nation.ID)
group by Name, Nation
having count(Name) > 1 and count(Nation) > 1
working?
I'm aiming for the result to be a table with columns:
ID -------First--------------- Last ---------Nation
where the last names and nations will be identical pairs while first names will be different.
I feel like the group by part isnt appropriate, but is there even an alternate way? Thanks for any help.
If you are using MS SQL Server:
select
*
from
(
select
Name.*,
Nation.Nation,
cnt = count(*) over(partition by LName, Nation)
from Name
join Nation on Nation.ID = Name.ID
) t
where cnt > 1
Try this:
SELECT * FROM (
SELECT Name.ID, Name.FName, Name.LName, Nation.Nation
FROM Name
INNER JOIN Nation ON (Name.ID = Nation.ID)
) a
INNER JOIN (
SELECT Name.ID, Name.FName, Name.LName, Nation.Nation
FROM Name
INNER JOIN Nation ON (Name.ID = Nation.ID)
) b ON (a.LName = b.LName AND a.Nation = b.Nation)
WHERE a.ID < b.ID
As Simon Righarts hinted, something's not right with the design.
Scenario 1)
If a name can have multiple nations, you would have 3 tables implementing an n:m relationship.
CREATE TABLE name (name_id int, name text, ...);
CREATE TABLE nation (nation_id int, nation text, ...);
CREATE TABLE nationality (name_id int references name(name_id)
,nation_id int references nation(nation_id)
... );
Query for the scenario:
SELECT a.name_id, a.fname, a.lname, n.nation
FROM name a
JOIN nationality na USING (name_id)
JOIN nation n USING (nation_id)
JOIN (
SELECT a.lname, na.nation_id
FROM name a
JOIN nationality na USING (name_id)
GROUP BY 1,2
HAVING count(*) > 1) x USING (lname, nation_id)
Scenario 2)
If a name can only have one nation, there would be a column nation_id in the table name:
CREATE TABLE name (name_id int
,name text
,nation_id int references nation(nation_id), ...);
CREATE TABLE nation (nation_id int, nation text, ...);
Query for this scenario:
SELECT a.name_id, a.fname, a.lname, n.nation
FROM name a
JOIN nation n USING (nation_id)
JOIN (
SELECT a.lname, a.nation_id
FROM name a
GROUP BY 1,2
HAVING count(*) > 1) x USING (lname, nation_id);
All multiple occurrences are included here, not just "pairs" - assuming you meant that.
Your actual description doesn't fit either scenario.