I have this table named Orders.
Each row of the table represents an order made by a customer.
prod means product
+-----------------------------------------------------------------------------------+
| prod_1 | prod_1_qty | prod_2 |prod_2_qty | prod_3 | prod_3_qty |
|-------------------------------------------------------|---------------------------|
| chair | 3 | board |9 | bed |4 |
| board | 8 | door |2 | desk |2 |
| chair | 2 | window |1 | door |6 |
| desk | 4 | chair |3 | sofa |1 |
I would like to write a query that returns the quantity of each product ordered like this:
+---------------------------+
| product | product_qty |
|---------------------------|
| chair | 8 |
| board | 17 |
| door | 8 |
| window | 1 |
| sofa | 1 |
| bed | 4 |
| desk | 6 |
Is there any way to achieve this using T-SQL, and if so, what is the query one would use to do this?
SELECT x.prod
, SUM(x.prod_qty) AS total
FROM (
SELECT prod1 AS prod, prod_qty AS total FROM table
UNION ALL
SELECT prod2 AS prod, prod_qty AS total FROM table
UNION ALL
SELECT prod3 AS prod, prod_qty AS total FROM table
) x
GROUP BY x.prod
Related
I am practicing SQL and here is my exercise(Table 1)
Table 1: The origin table
My goal is to have the sum of income when Month is between 1 and 3. If Month=4, the income senter code herehould not be added in.
|M_Id | Year | Month | CompanyID | CustomerID | MonthIncome |
|1 | 110 | 1 | T012 | C001 | 30000 |
|2 | 110 | 2 | T012 | C001 | 60000 |
|3 | 110 | 3 | T012 | C001 | 60000 |
|4 | 110 | 4 | T012 | C001 | 100000 |
|5 | 110 | 1 | A012 | A001 | 10000 |
|6 | 110 | 1 | A012 | A001 | 50000 |
I tried some SQL:
select companyID, customerID, Year, Sum(MonthIncome) as Total
from[dbo].[Money]
group by year,companyID, customerID
and the table result look like this:
Table 2. using sum, group by , and the table become
| Year | CompanyID | CustomerID | MonthIncome|
| 110 | A012 | A001 | 60000|
| 110 | T012 | C001 | 250000|
The table style is what I want, but the sum(Income) is not right because it had included month=4.
I tried to change my sql to
select companyID, customerID, Year, Sum(MonthIncome) as Total
from[dbo].[Money]
group by year,companyID, customerID
having month between 1 and 3
but the system as me to put the month into group by, and then table style is not what I want.
Could anybody help me?
You can exclude the months that are not in the range 1 to 3 using WHERE then do the grouping:
SELECT year, companyID, customerID, Sum(MonthIncome) AS Total
FROM [dbo].[Money]
WHERE month BETWEEN 1 AND 3
GROUP BY year, companyID, customerID;
For a set of invoice stage records by project I'm trying to determine a billing cycle using the ID of the starting invoice stage.
Here's the table - InvoiceStages
|ID| Project | StageDate | InvoiceStage | StageFlag | BillCycle |
|1 | abc123 | 10-May-18 | Finance | S | 1 |
|2 | abc123 | 15-May-18 | Review Draft | | 1 |
|4 | abc123 | 19-May-18 | Approved - NO Changes | | 1 |
|7 | abc123 | 21-May-18 | Final Invoice | E | 1 |
|9 | abc123 | 05-Jun-18 | Finance | S | 9 |
|12| abc123 | 07-Jun-18 | Review Draft | | 9 |
|15| abc123 | 09-Jun-18 | Approved - With Changes | | 9 |
|21| abc123 | 10-Jun-18 | Review Draft | | 9 |
|25| abc123 | 12-Jun-18 | Approved - NO Changes | | 9 |
|40| abc123 | 13-Jun-18 | Final Invoice | E | 9 |
|3 | xyz789 | 15-May-18 | Finance | S | 3 |
|5 | xyz789 | 19-May-18 | Review Draft | | 3 |
|6 | xyz789 | 20-May-18 | Approved - NO Changes | | 3 |
|8 | xyz789 | 22-May-18 | Final Invoice | E | 3 |
|10| xyz789 | 06-Jun-18 | Finance | S | 10 |
|11| xyz789 | 07-Jun-18 | Review Draft | | 10 |
|18| xyz789 | 09-Jun-18 | Approved - NO Changes | | 10 |
|22| xyz789 | 11-Jun-18 | Final Invoice | E | 10 |
I've looked at LAG / LEAD but wasn't sure if that would be the best option.
Select
ID
, Project
, StageDate
, InvoiceStage
, StageFlag
, ?? As BillCycle
From InvoiceStages
I expect the output for BillCycle to be the ID of the first record where StageFlag = 'S' for all records up to and including the end stage 'E'. Then the next set will start with the ID starting with 'S' again.
You can assign a group using a cumulative sum and then use a window function to get the value:
select i.*,
max(id) over (partition by project, grp) as invoice_id
from (select i.*,
sum(case when i.stageflag = 'S' then 1 else 0 end) over (partition by i.project order by i.stagedate) as grp
from InvoiceStages i
) i;
If the ids increase along with the date, you can do this without a subquery:
select i.*,
max(case when stageflag = 'S' then id end) over (partition by project) as invoice_id
from invoicestages i;
i have the following Problem:
A Table with Bills contains for example three Columns Hospital , Bill-Number and Bill-Amount.
---------------------------------
| hospital | Number | Amount |
---------------------------------
| a | 33 | 20 |
---------------------------------
| a | 11 | 10 |
---------------------------------
| a | 5 | 40 |
---------------------------------
| a | 34 | 55 |
---------------------------------
| b | 3 | 20 |
---------------------------------
| b | 9 | 30 |
---------------------------------
| b | 11 | 15 |
---------------------------------
The Bill-Numbers have range like from 0-9 and from 10-19 and from 20-29 and from 30-39
So I need a Result-Table that shows me the Hospital and the Total Amount and all the Bills that belongs to the same Range together like :
----------------------------------------------
|Hospital | range1|range2|range3|range4|Total|
----------------------------------------------
|a | 5 |11 |0 |67 |93 |
----------------------------------------------
|b | 12 | 11 | 0 | 0 |23 |
----------------------------------------------
I could easily get the hospital and the total ( normal group by and sum function ) but when i try to get this ranges thing it doesnt work.
Could anyone help me with this point?
You can use conditional aggregation:
select hospital,
sum(case when number between 0 and 9 then amount else 0 end) as range1,
. . .
from bills b
group by hospital;
I'm quite new to SQL - hope you can help:
I have several tables that all have 3 columns in common: ObjNo, Date(year-month), Product.
Each table has 1 other column, that represents an economic value (sales, count, netsales, plan ..)
I need to join all tables on the 3 common columns giving. The outcome must have one row for each existing combination of the 3 common columns. Not every combination exists in every table.
If I do full outer joins, I get ObjNo, Date, etc. for each table, but only need them once.
How can I achieve this?
+--------------+-------+--------+---------+-----------+
| tblCount | | | | |
+--------------+-------+--------+---------+-----------+
| | ObjNo | Date | Product | count |
| | 1 | 201601 | Snacks | 22 |
| | 2 | 201602 | Coffee | 23 |
| | 4 | 201605 | Tea | 30 |
| | | | | |
| tblSalesPlan | | | | |
| | ObjNo | Date | Product | salesplan |
| | 1 | 201601 | Beer | 2000 |
| | 2 | 201602 | Sancks | 2000 |
| | 5 | 201605 | Tea | 2000 |
| | | | | |
| | | | | |
| tblSales | | | | |
| | ObjNo | Date | Product | Sales |
| | 1 | 201601 | Beer | 1000 |
| | 2 | 201602 | Coffee | 2000 |
| | 3 | 201603 | Tea | 3000 |
+--------------+-------+--------+---------+-----------+
Thx
Devon
It sounds like you're using SELECT * FROM... which is giving you every field from every table. You probably only want to get the values from one table, so you should be explicit about which fields you want to include in the results.
If you're not sure which table is going to have a record for each case (i.e. there is not guaranteed to be a record in any particular table) you can use the COALESCE function to get the first non-null value in each case.
SELECT COALESCE(tbl1.ObjNo, tbl2.ObjNo, tbl3.ObjNo) AS ObjNo, ....
tbl1.Sales, tbl2.Count, tbl3.Netsales
Actually I am stuck in one issue. I have a table:
tbl_color
+------------+
|id | name |
|---|--------|
|1 | Red |
|---|--------|
|2 | Blue |
|---|--------|
|3 | Black |
+------------+
tbl_clothes
+----------------+
|id | name |
| 1 | Pant |
| 2 | Shirt |
| 3 | T-shirt |
+----------------+
tb_sales
+---------------------------------------+
|id | id_cloth | id_color | sales_date |
|---|----------|-----------|------------|
|1 | 1 | 1 | 2016/1/1 |
|---|----------|-----------|------------|
|2 | 1 | 3 | 2016/1/1 |
|---|----------|-----------|------------|
|3 | 1 | 1 | 2016/2/2 |
+---------------------------------------+
So when I change one row of tbl_color to
tbl_color
+---------------------------+
|id | name | modified_on |
|----|--------|-------------|
|1 | Orange | 2016/3/2 |
|----|--------|-------------|
|2 | Blue | 2016/1/2 |
|----|--------|-------------|
|3 | Black | 2016/1/2 |
+---------------------------+
So when I want to get report of sales on 2016/1/1
SELECT * from table tb_sales
JOIN tbl_clothes ON tbl_clothes.id = tbl_sales.id_cloth
JOIN tbl_sales ON tbl_color.id = tbl_sales.id_color
where sales_date = '2016/1/1'
I get the report that have been modified no the original sales
How can I handle this issue?