Generate report using SUM - sql-server-2005

I've got two SQL Server 2005 tables: MainTable and Orders.
MainTable:
| MainID | Serial |
-------------------
| 1 | A00001 |
| 2 | B00002 |
Orders:
| OrderID | MainID | Name | Value |
-----------------------------------
| 1 | 2 | John | 100 |
| 2 | 2 | Mike | 200 |
| 3 | 1 | John | 150 |
| 4 | 1 | Mike | 350 |
| 5 | 1 | John | 200 |
| 6 | 2 | John | 500 |
| 7 | 1 | Mike | 50 |
I want to get something like this:
|Serial | Name | Total |
-----------------------
| A00001 | John | 350 |
| A00002 | John | 600 |
| A00001 | Mike | 400 |
| A00002 | Mike | 200 |

SELECT
m.serial,
o.name,
SUM(o.value)
FROM
main m
INNER JOIN order o ON m.mainid = o.mainid
GROUP BY
o.name,
m.serial

select serial, name, sum(value) as total
from maintable m inner join orders o on
m.mainID = o.mainID
group by
serial, name

SELECT
M.SERIAL, O.NAME, SUM(VALUE) AS TOTAL
FROM MAINTABLE M JOIN ORDERS O ON O.MAINID=M.MAINID
GROUP BY M.SERIAL, O.NAME

select Serial , name , Total
from MainTable m,
( select MainID ,name, SUM(value) Total from Orders o group by MainID , Name ) O
where m.MainID= O.MainID

Related

Need query for JOIN four tables with some conditions?

I have the following four tables:
1) mls_user
2) mls_category
3) bonus_point
4) mls_entry
In mls_user table values are like below:
*-------------------------*
| id | store_id | name |
*-------------------------*
| 1 | 101 | sandeep |
| 2 | 101 | gagan |
| 3 | 102 | santosh |
| 4 | 103 | manu |
| 5 | 101 | jagveer |
*-------------------------*
In mls_category table values are like below:
*---------------------------------*
| cat_no | store_id | cat_value |
*---------------------------------*
| 20 | 101 | 1 |
| 21 | 101 | 4 |
| 30 | 102 | 1 |
| 31 | 102 | 2 |
| 40 | 103 | 1 |
| 41 | 103 | 1 |
*---------------------------------*
In bonus_point table values are like below:
*-----------------------------------*
| user_id | store_id | bonus_point |
| 1 | 101 | 10 |
| 4 | 101 | 5 |
*-----------------------------------*
In mls_entry table values are like below:
*-------------------------------------------------------*
| user_id | store_id | category | distance | status |
*-------------------------------------------------------*
| 1 | 101 | 20 | 10 | Approved |
| 1 | 101 | 21 | 40 | Approved |
| 1 | 101 | 20 | 10 | Approved |
| 2 | 101 | 20 | 5 | Approved |
| 3 | 102 | 30 | 10 | Approved |
| 3 | 102 | 31 | 80 | Approved |
| 4 | 101 | 20 | 15 | Approved |
*-------------------------------------------------------*
And I want below output:
*--------------------------------------------------*
| user name | Points | bonus Point | Total Point |
*--------------------------------------------------*
| Sandeep | 30 | 10 | 40 |
| Santosh | 30 | 0 | 30 |
| Manu | 15 | 5 | 20 |
| Gagan | 5 | 0 | 5 |
| Jagveer | 0 | 0 | 0 |
*--------------------------------------------------*
I tell the calculation of how the points will come for user Sandeep.
Points = ((10+10)/1 + 40/4)=30
Here 1 and 4 is cat value which comes from mls_category.
I am using below code for a particular user but when i
SELECT sum(t1.totald/c.cat_value) as total_distance
FROM mls_category c
join (
select sum(distance) totald, user_id, category
FROM mls_entry
WHERE user_id=1 AND store_id='101' AND status='approved'
group by user_id, category) t1 on c.cat_no = t1.category
I have created tables in online for checking
DEMO
Computing the points (other than the bonus points) requires a separate join between the mls_entry and mls_category tables. I would do this in a separate subquery, and then join this to the larger query.
Here is one approach:
SELECT
u.name,
COALESCE(t1.points, 0) AS points,
COALESCE(b.bonus_point, 0) AS bonus_points,
COALESCE(t1.points, 0) + COALESCE(b.bonus_point, 0) AS total_points
FROM mls_user u
LEFT JOIN
(
SELECT e.user_id, SUM(e.distance / c.cat_value) AS points
FROM mls_entry e
INNER JOIN mls_category c
ON e.store_id = c.store_id AND e.category = c.cat_no
GROUP BY e.user_id
) t1
ON u.id = t1.user_id
LEFT JOIN bonus_point b
ON u.id = b.user_id
ORDER BY
total_points DESC;
This is the output I am getting from the above query in the demo you setup:
The output does not match exactly, because you have (perhaps) a typo in Santosh's data in your question, or otherwise the expected output in your question has a typo.

How to remove duplicate values from oracle join?

I want to create a view that present only the results and not present the duplicates, I have 3 tables in oracle database:
The first table contain general information about a person
+-----------+-------+-------------+
| ID | Name | Birtday_date|
+-----------+-------+-------------+
| 1 | Byron | 12/10/1998 |
| 2 | Peter | 01/11/1973 |
| 4 | Jose | 05/02/2008 |
+-----------+-------+-------------+
The second table contain information about a telephone of the people in the first table.
+-------+----------+----------+----------+
| ID |ID_Person |CELL_TYPE | NUMBER |
+-------+- --------+----------+----------+
| 1221 | 1 | 3 | 099141021|
| 2221 | 1 | 2 | 099091925|
| 3222 | 1 | 1 | 098041013|
| 4321 | 2 | 1 | 088043153|
| 4561 | 2 | 2 | 090044313|
| 5678 | 4 | 1 | 092049013|
| 8990 | 4 | 2 | 098090233|
+----- -+----------+----------+----------+
The Third table contain information about a email of the people in the first table.
+------+----------+----------+---------------+
| ID |ID_Person |MAIL_TYPE | Email |
+------+- --------+----------+---------------+
| 221 | 1 | 1 |jdoe#aol.com |
| 222 | 1 | 2 |jdoe1#aol.com |
| 421 | 2 | 1 |xx12#yahoo.com |
| 451 | 2 | 2 |dsdsa#gmail.com|
| 578 | 4 | 1 |sasaw1#sdas.com|
| 899 | 4 | 2 |cvcvsd#wew.es |
+------+----------+----------+---------------+
if i do a inner join with this tables the result will do something like that
+-----+-------+-------------+----------+----------+----------+----------------+
| ID | Name | Birtday_date| CELL_TYPE| NUMBER |MAIL_TYPE|Email |
+-----+-------+-------------+----------+----------+----------+----------------+
| 1 | Byron | 12/10/1998 | 3 | 099141021|1 |jdoe#aol.com |
| 1 | Byron | 12/10/1998 | 3 | 099141021|2 |jdoe1#aol.com |
| 1 | Byron | 12/10/1998 | 2 | 099091925|1 |jdoe#aol.com |
| 1 | Byron | 12/10/1998 | 2 | 099091925|2 |jdoe1#aol.com |
| 1 | Byron | 12/10/1998 | 1 | 098041013|1 |jdoe#aol.com |
| 1 | Byron | 12/10/1998 | 1 | 098041013|2 |jdoe1#aol.com |
| 2 | Peter | 01/11/1973 | 1 | 088043153|1 |xx12#yahoo.com |
| 2 | Peter | 01/11/1973 | 1 | 088043153|2 |dsdsa#gmail.com |
| 2 | Peter | 01/11/1973 | 2 | 090044313|1 |xx12#yahoo.com |
| 2 | Peter | 01/11/1973 | 2 | 090044313|2 |dsdsa#gmail.com |
| 4 | Jose | 05/02/2008 | 1 | 088043153|1 |sasaw1#sdas.com |
| 4 | Jose | 05/02/2008 | 1 | 088043153|2 |cvcvsd#wew.es |
| 4 | Jose | 05/02/2008 | 2 | 088043153|1 |sasaw1#sdas.com |
| 4 | Jose | 05/02/2008 | 2 | 088043153|2 |cvcvsd#wew.es |
+-----+-------+-------------+----------+----------+----------+----------------+
So the result that i will to present in a view is the next
+-----+-------+-------------+----------+----------+----------+----------------+
| ID | Name | Birtday_date| CELL_TYPE| NUMBER |MAIL_TYPE|Email |
+-----+-------+-------------+----------+----------+----------+----------------+
| 1 | Byron | 12/10/1998 | 3 | 099141021|1 |jdoe#aol.com |
| 1 | Byron | 12/10/1998 | | |2 |jdoe1#aol.com |
| 1 | Byron | 12/10/1998 | 2 | 099091925| | |
| 1 | Byron | 12/10/1998 | 1 | 098041013| | |
| 2 | Peter | 01/11/1973 | 1 | 088043153|1 |xx12#yahoo.com |
| 2 | Peter | 01/11/1973 | | |2 |dsdsa#gmail.com |
| 2 | Peter | 01/11/1973 | 2 | 090044313| | |
| 4 | Jose | 05/02/2008 | 1 | 092049013|1 |sasaw1#sdas.com |
| 4 | Jose | 05/02/2008 | | |2 |cvcvsd#wew.es |
| 4 | Jose | 05/02/2008 | 2 | 098090233| | |
+-----+-------+-------------+----------+----------+----------+----------------+
I tried to achieve a similar output using
case
when row_number() over (partition by table1.id order by table2.type) = 1
then table1.value
end
as "VALUE"
But the result is nothing that I expect and some rows they repeats
What you need to do is enumerate the rows and then join on those enumerations. This is tricky, because you don't know how many are in each list. Well, there is another method using conditional aggregation:
select p.id, p.name, p.birthday,
max(cell_type) as cell_type, max(number) as number,
max(mail_type) as mail_type, max(email) as email
from person p left join
((select id_person, cell_type, number,
null as mail_type, null as email,
row_number() over (partition by id_person order by number) as seqnum
from phones
) union all
(select id_person, null as cell_type, null as number,
mail_type, email,
row_number() over (partition by id_person order by email) as seqnum
from emails
)
) pe
on pe.id_person = p.id_person
group by p.id, p.name, p.birthday, pe.seqnum
Hope this helps.
Create table person(ID int ,Name varchar(20), Birtday_date date)
Insert into person values
(1,'Byron' ,'12/10/1998'),
(2,'Peter' ,'01/11/1973'),
(4,'Jose ' ,'05/02/2008')
Create table phones (ID int,ID_Person int,CELL_TYPE int,NUMBER float)
Insert into phones values
(1221, 1 , 3,099141021),
(2221, 1 , 2,099091925),
(3222, 1 , 1,098041013),
(4321, 2 , 1,088043153),
(4561, 2 , 2,090044313),
(5678, 4 , 1,092049013),
(8990, 4 , 2,098090233)
Create table emails(ID int,ID_Person int, MAIL_TYPE int, Email varchar(100))
Insert into emails values
(221, 1 , 1, 'jdoe#aol.com '),
(222, 1 , 2, 'jdoe1#aol.com '),
(421, 2 , 1, 'xx12#yahoo.com '),
(451, 2 , 2, 'dsdsa#gmail.com'),
(578, 4 , 1, 'sasaw1#sdas.com'),
(899, 4 , 2, 'cvcvsd#wew.es ')
select p.id, p.name, p.Birtday_date,
case when Lag(number) over(partition by p.id order by p.id,pe.id) = number then null else cell_type end as cell_type,
case when Lag(number) over(partition by p.id order by p.id,pe.id) = number then null else number end as number,
mail_type as mail_type, email as email
from person p left join
(select pp.ID_Person, cell_type, number, mail_type, email,pp.id from
(select ID_Person, cell_type, number,id,
row_number() over (partition by ID_Person order by id ) as seqnum
from phones
) pp left join
(select ID_Person,
mail_type, email, 1 as seqnum
from emails
)e on pp.ID_Person = e.ID_Person and pp.seqnum = e.seqnum
) pe
on pe.ID_Person = p.Id
order by p.id, pe.id

How to SUM rows with an outer join?

Question:
I have the following tables that I'd like to sum on two fields: HOURS and RATE. I also want to retrieve the NAME from the third table, joining all 3 tables on the field LINE_NUM.
If the LINE_NUM and CODE are the same, sum the fields of A with B.
Table EARNINGS A:
| EMPLOYEE_ID | LINE_NUM | REG_CODE | REG_HOURS | REG_RATE |
------------------------------------------------------------
| 0001 | 1 | C | 20 | 200 |
| 0002 | 1 | H | 0 | 0 |
Table OTH_EARNINGS B:
| LINE_NUM | OTH_CODE | OTH_HOURS | OTH_RATE |
----------------------------------------------
| 1 | A | 0 | 0 |
| 1 | B | 0 | 0 |
| 1 | C | 10 | 100 |
| 2 | A | 50 | 50 |
Table PAYCHECK C:
| EMPLOYEE_ID | LINE_NUM | NAME |
---------------------------------
| 0001 | 1 | Tom |
| 0001 | 2 | Tom |
| 0002 | 1 | John |
The result I'm looking for should be:
| EMPLOYEE_ID | LINE_NUM | CODE | HOURS | RATE | NAME |
-------------------------------------------------------
| 0001 | 1 | A | 0 | 0 | Tom |
| 0001 | 1 | B | 0 | 0 | Tom |
| 0001 | 1 | C | 30 | 300 | Tom |
| 0001 | 2 | A | 50 | 50 | Tom |
| 0002 | 1 | H | 0 | 0 | John |
Any idea how I can achieve this?
What I tried:
I've tried (table A with C) UNION (table B with C), but I can't get the sums to work.
SELECT C.EMPLOYEE_ID, A.REG_CODE, A.REG_HRS, SUM(A.REG_RATE)
FROM EARNINGS A, PAYCHECK C
WHERE A.LINE_NUM = C.LINE_NUM
GROUP BY C.EMPLOYEE_ID, A.REG_CODE, A.REG_HRS
UNION
SELECT D.EMPLOYEE_ID, B.OTH_CODE, B.OTH_HRS, SUM(B.OTH_RATE)
FROM OTH_EARNINGS B, PAYCHECK D
WHERE B.LINE_NUM = D.LINE_NUM
GROUP BY D.EMPLOYEE_ID, B.OTH_CODE, B.OTH_HRS
But I couldn't get the sum to work and it returned:
| EMPLOYEE_ID | LINE_NUM | CODE | HOURS | RATE | NAME |
-------------------------------------------------------
| 0001 | 1 | A | 0 | 0 | Tom |
| 0001 | 1 | B | 0 | 0 | Tom |
| 0001 | 1 | C | 10 | 100 | Tom |
| 0001 | 1 | C | 20 | 200 | Tom |
| 0001 | 2 | A | 50 | 50 | Tom |
| 0002 | 1 | H | 0 | 0 | John |
Your approach wasn't bad and you were almost there.
You should make the GROUP BY on the results of the 2 UNIONed queries being nested:
SELECT EMPLOYEE_ID, NAME, CODE, SUM(HRS), SUM(RATE)
FROM
(
SELECT C.EMPLOYEE_ID, C.NAME, A.REG_CODE AS CODE, A.REG_HRS AS HRS, A.REG_RATE AS RATE
FROM EARNINGS A
INNER JOIN PAYCHECK C ON A.LINE_NUM = C.LINE_NUM
UNION ALL
SELECT D.EMPLOYEE_ID, C.NAME, B.OTH_CODE AS CODE, B.OTH_HRS AS HRS, B.OTH_RATE AS RATE
FROM OTH_EARNINGS B
INNER JOIN PAYCHECK D ON B.LINE_NUM = D.LINE_NUM
)
GROUP BY EMPLOYEE_ID, NAME, CODE
However this will return wrong results because the JOINs on the PAYCHECK table will returns duplicates.
There's obviously something missing somewhere.
To identify the employee, you should combine 2 columns : EMPLOYEE_ID and LINE_NUM. For the first query on EARNING, there's no issue as the EMPLOYEE_ID is present in the table. However for the second query on OTH_EARNINGS, the EMPLOYEE_ID is missing...
In theory you should have something like this (check the INNER JOIN...ON)
SELECT EMPLOYEE_ID, NAME, CODE, SUM(HRS), SUM(RATE)
FROM
(
SELECT C.EMPLOYEE_ID, C.NAME, A.REG_CODE AS CODE, A.REG_HRS AS HRS, A.REG_RATE AS RATE
FROM EARNINGS A
INNER JOIN PAYCHECK C ON A.LINE_NUM = C.LINE_NUM AND A.EMPLOYEE_ID = C.EMPLOYEE_ID
UNION ALL
SELECT D.EMPLOYEE_ID, C.NAME, B.OTH_CODE AS CODE, B.OTH_HRS AS HRS, B.OTH_RATE AS RATE
FROM OTH_EARNINGS B
INNER JOIN PAYCHECK D ON B.LINE_NUM = D.LINE_NUM AND B.EMPLOYEE_ID = D.EMPLOYEE_ID
)
GROUP BY EMPLOYEE_ID, NAME, CODE
I also changed from your initial query:
the JOINs from implicit to explicit syntax.
the UNION into an UNION ALL as there's no reason here to remove the duplicates (maybe I am wrong)

I can't get my desired SQL result

I have two tables:
Owners
+----+------+------------+
| id | name | birth_year |
+----+------+------------+
| 1 | John | 1970 |
| 2 | Jane | 1980 |
| 3 | Jack | 1990 |
| 4 | Josh | 2000 |
+----+------+------------+
Buylog
+----+----------+------------+
| id | owner_id | date |
+----+----------+------------+
| 1 | 1 | 01/01/2016 |
| 2 | 2 | 01/02/2016 |
| 3 | 2 | 01/03/2016 |
| 4 | 1 | 01/04/2016 |
+----+----------+------------+
I need to get all the info from Owners table plus the count of buys per owner:
+-----------+-------------+-------------------+--------------+
| owners.id | owners.name | owners.birth_year | buylog.Count |
+-----------+-------------+-------------------+--------------+
| 1 | John | 1970 | 2 |
| 2 | Jane | 1980 | 2 |
| 3 | Jack | 1990 | 0 |
| 4 | Josh | 2000 | 0 |
+-----------+-------------+-------------------+--------------+
I tried the below query, but that returns with error:
Select
o.id,
o.name,
o.birth_year,
Count(b.id) as Count
From
owners o
Left Outer Join
buylog b
On
b.owner_id = o.id
The error message should be pretty clear, you are missing a group by clause:
Select
o.id,
o.name,
o.birth_year,
Count(b.id) as Count
From
owners o
Left Outer Join
buylog b
On
b.owner_id = o.id
Group By o.id,
o.name,
o.birth_year
Query by HoneyBadger will do just fine, however this might perform better:
SELECT o.id
, o.name
, o.birth_year
, COALESCE(b.Count, 0) AS Count
FROM owners o
LEFT JOIN (
SELECT owner_id, COUNT(*) AS Count
FROM buylog
GROUP BY owner_id
) AS b
ON b.owner_id = o.id;
It should bring exactly the same result.
SELECT o.*,
CASE
WHEN temp.Buylog_count IS NULL THEN 0
ELSE temp.Buylog_count
END
FROM Owners o
LEFT JOIN
(
SELECT b.owner_id AS oid, COUNT(*) AS Buylog_count
FROM Buylog b
GROUP BY b.owner_id
)temp ON temp.oid = o.id

Distinct on one column with multiple results

I have a problem with my query through visual basic to access database. Lets say I have two tables as bellow.
+-------+-------------+-------------+------------+
| ID | Date1 | Date2 | CustomerID |
+-------+-------------+-------------+------------+
| 1 | 1-1-2013 | 1-1-2012 | 1 |
| 2 | 1-1-2013 | 1-1-2012 | 1 |
| 3 | 1-1-2013 | 1-1-2012 | 2 |
| 4 | 1-1-2013 | 1-1-2012 | 3 |
| 5 | 1-1-2013 | 1-1-2012 | 3 |
+-------+-------------+-------------+------------+
and
+----------+---------+
| ID | Name |
+----------+---------+
| 1 | John |
| 2 | Tina |
| 3 | Patrick |
+----------+---------+
I would like to get result with only unique numbers from Customer - ID in first table like this one bellow.
+----------+----------+-------------+------------+
| ID | Date1 | Date2 | CustomerID |
+----------+----------+-------------+------------+
| 1 | 1-1-2013 | 1-1-2012 | 1 |
| 3 | 1-1-2013 | 1-1-2012 | 2 |
| 4 | 1-1-2013 | 1-1-2012 | 3 |
+----------+----------+-------------+------------+
I've tried with this query but with no luck.
sqL = " SELECT DISTINCT Order.ID, Order.Date1, Order.Date2, Customer.Name
FROM Order (Order INNER JOIN Customer ON Order.CustomerID = Customer.ID)"
But the code does not give me the result I wanted. Can you please provide me some help with my query.
UPDATED This will do it
SELECT q.OrderID, o.Date1, o.Date2, o.CustomerID, c.Name AS CustomerName
FROM
(
(SELECT CustomerID, MIN(ID) AS OrderID
FROM [Order]
GROUP BY CustomerID
) AS q INNER JOIN [Order] AS o
ON q.OrderID = o.ID
) INNER JOIN Customer AS c
ON o.CustomerID = c.ID
Output:
OrderID | Date1 | Date2 | CustomerID | CustomerName
--------|----------|----------|------------|-------------
1 | 1/1/2013 | 1/1/2012 | 1 | John
3 | 1/1/2013 | 1/1/2013 | 2 | Tina
4 | 1/1/2013 | 1/1/2012 | 3 | Patrick
UPDATE: Based on your comments your real query might look like
SELECT q.ID, o.ID_narocila, o.datum_sprejema, o.rok_izdobave, o.status_artikla, o.status_narocila o.ID_stranke, c.naziv
FROM
(
(SELECT ID_stranke, MIN(ID) AS ID
FROM Narocilo
GROUP BY ID_stranke
) AS q INNER JOIN Narocilo AS o
ON q.ID = o.ID
) INNER JOIN Stranke AS c
ON o.ID_stranke = c.ID
From the desired result set you have shown, the following query will work:
SELECT Min(T2.ID) AS MinOfID, Min(T1.Date1) AS MinOfDate1, Min(T1.Date2) AS MinOfDate2, T1.CustomerID
FROM T2 INNER JOIN T1 ON T2.ID = T1.CustomerID
GROUP BY T1.CustomerID;