I have 2 tables: Income (InvoiceDate, TotalAmount) and Outcome (ExpenseDate, TotalAmount).
Suppose that I have data for each column as below:
Income:
| INVOICEDATE | TOTALAMOUNT |
|-------------|-------------|
| 2013-10-16 | 22000 |
| 2013-10-17 | 14400 |
| 2013-10-18 | 4488 |
Outcome:
| EXPENSEDATE | TOTALAMOUNT |
|-------------|-------------|
| 2013-10-25 | 15 |
I want to merge these 2 tables to show as below:
| DATE | INCOME | OUTCOME |
|------------|--------|---------|
| 2013-10-25 | 0 | 15 |
| 2013-10-16 | 22000 | 0 |
| 2013-10-17 | 14400 | 0 |
| 2013-10-18 | 4488 | 0 |
However when I run my T-SQL, It will show like this instead:
| DATE | INCOME | OUTCOME |
|------------|--------|---------|
| (null) | (null) | 15 |
| 2013-10-16 | 22000 | (null) |
| 2013-10-17 | 14400 | (null) |
| 2013-10-18 | 4488 | (null) |
This is my T-SQL:
SELECT
CASE (income.InvoiceDate)
WHEN NULL THEN Outcome.expenseDate
ELSE income.InvoiceDate
END AS [Date],
CASE (income.TotalAmount)
WHEN NULL THEN 0
ELSE income.TotalAmount
END AS Income,
CASE (Outcome.TotalAmount)
WHEN NULL THEN 0
ELSE Outcome.TotalAmount
END AS Outcome
FROM
Outcome
FULL OUTER JOIN
income ON Outcome.expenseDate = income.InvoiceDate
WHERE
NOT (
Outcome.TotalAmount = 0
AND income.TotalAmount = 0
)
You can test this SQL at http://sqlfiddle.com/#!6/3589f/1
Does anyone know what's wrong with my T-SQL?
Thank You!
Pengan
A CASE statement is a shorthand for a series of = operators. However, NULL is never equal to any value (that's what the IS operator is for), so using CASE to evaluate NULLs is somewhat pointless.
Instead, you can yse the COALESCE function to replace your NULLs with 0s as following:
SELECT Outcome.expenseDate AS [Date],
COALESCE(Income.TotalAMount, 0) AS Income,
COALESCE(Outcome.TotalAMount, 0) AS Outcome
FROM Outcome
FULL OUTER JOIN income ON Outcome.expenseDate = income.InvoiceDate
WHERE NOT (
Outcome.TotalAmount = 0
AND income.TotalAmount = 0
)
You may want a union instead
select InvoiceDate as Date, TotalAmount as Income, 0 as Outcome from Income
union all
select ExpenseDate, 0, TotalAmount from Outcome
If you can have income and expenses on the same date, you can group them from this.
select [date], Sum(Income), Sum(outcome) from
(
select InvoiceDate as Date, TotalAmount as Income, 0 as Outcome from Income
union all
select ExpenseDate, 0, TotalAmount from Outcome
) v
group by [date]
As to what is wrong with your statement, the problem is with the case.
They should use is null rather than when null
CASE WHEN income.TotalAmount IS NULL THEN 0 ELSE income.TotalAmount end,
But a shorter way is to use ISNULL
ISNULL(income.TotalAmount, 0)
Related
I have an sql script below.
SELECT
InvoiceNo
,InvoiceType
,Amount
,OrderAmount
,ShippingAmount
,TruckTaxAmount
,PreShippingAmount
FROM truckdb AS t1
INNER JOIN truckdetails AS t2 ON tl.truckdetail = t2.truckid
WHERE [shipping date] > = '01-01-2011'
And sample data
+--------+-------------+---------+-------------+----------------+------------+----------+
| InvNo | InvoiceType | Amount | OrderAmount | ShippingAmount | TruckTxAmt | PreShAmt |
+--------+-------------+---------+-------------+----------------+------------+----------+
| 001 | ckt | 1200 | 544 | 666 | 23 | 11 |
| 002 | tkp | 1300 | 544 | 133 | 11 | 11 |
| 009 | ckt | 1222 | 221 | 122 | 221 | 566 |
+--------+-------------+---------+-------------+----------------+------------+----------+
I have several invoice types. I want to show one particular CKT InvoiceType - Amount, OrderAmount, ShippingAmount, TruckTaxAmount in negative. I tried to multiply using when statement after where clause. But something is wrong.
You need to use the CASE WHEN in the SELECT clause, not after the WHERE clause:
SELECT
...
CASE WHEN InvoiceType='CKT' THEN Amount * -1.00 ELSE Amount END AS Amount,
CASE WHEN InvoiceType='CKT' THEN OrderAmount * -1.00 ELSE OrderAmount END AS OrderAmount,
(etc)
...
FROM ...
Thanks, #Tab Alleman
SELECT ... CASE WHEN InvoiceType='CKT' THEN Amount * -1.00 ELSE Amount END AS Amount,
CASE WHEN InvoiceType='CKT' THEN OrderAmount * -1.00 ELSE OrderAmount END AS
OrderAmount, (etc) ... FROM ... ------------------------------------------------------------------------
Given the following table structure
CustomerID | Balance | Date
1 | 100.00 | 07-09-2016
1 | -50.00 | 08-09-2016
1 | -60.00 | 09-09-2016
1 | 500.00 | 10-09-2016
1 | 600.00 | 11-09-2016
1 | -100.00 | 12-09-2016
1 | -200.00 | 13-09-2016
1 | -400.00 | 14-09-2016
1 | -500.00 | 15-09-2016
I want to start from bottom and select all rows that has negative balance and stop once credit balance is found. For above example data, I want result to be as below
1 | -100.00 | 12-09-2016
1 | -200.00 | 13-09-2016
1 | -400.00 | 14-09-2016
1 | -500.00 | 15-09-2016
How do I achieve this?
Thanks.
Easiest way is to use NO EXISTS. Return a row if no other row with a later date has a positive balance:
select *
from tablename t1
where not exists (select * from tablename t2
where t2.Balance > 0
and t2.date > t1.date)
Or, let the sub-query return latest date with a balance > 0:
select *
from tablename
where date > (select max(date) from tablename where balance > 0)
I've come across certain logic that I need for my SQL query. Given that I have a table as such:
+----------+-------+------------+
| product | valid | Date |
+----------+-------+------------+
| 1 | null | 2016-05-10 |
| 1 | null | 2016-05-09 |
| 1 | yes | 2016-05-08 |
+----------+-------+------------+
This table is produced by a simple query:
SELECT * FROM products WHERE product = 1 ORDER BY date desc
Now what I need to do is create a query to count the number of nulls for certain products by order of date until there is a yes value. So the above example the count would be 2 as there are 2 nulls until a yes.
+----------+-------+------------+
| product | valid | Date |
+----------+-------+------------+
| 2 | null | 2016-05-10 |
| 2 | yes | 2016-05-09 |
| 2 | null | 2016-05-08 |
+----------+-------+------------+
Above would return 1 as there is 1 null until a yes.
+----------+-------+------------+
| product | valid | Date |
+----------+-------+------------+
| 3 | yes | 2016-05-10 |
| 3 | yes | 2016-05-09 |
| 3 | null | 2016-05-08 |
+----------+-------+------------+
Above would return 0.
You need a Correlated Subquery like this:
SELECT COUNT(*)
FROM products AS p1
WHERE product = 1
AND Date >
( -- maximum date with 'yes'
SELECT MAX(Date)
FROM products AS p2
WHERE p1.product = p2.product
AND Valid = 'yes'
)
This should do it:
select count(1) from table where valid is null and date > (select min(date) from table where valid = 'yes')
Not sure if your logic provided covers all the possible weird and wonderful extreme scenarios but the following piece of code would do what you are after:
select a.product,
count(IIF(a.valid is null and a.date >maxdate,a.date,null)) as total
from sometable a
inner join (
select product, max(date) as Maxdate
from sometable where valid='yes' group by product
) b
on a.product=b.product group by a.product
i need to do one select with different where clauses (with different product code). The result which i need is below.
I have table like:
ApID | Date | Code | Qty | Price | Sum
222 | 2014-10-11 | 555 | 1 | 2,22 | 2,22
222 | 2014-10-11 | 555 | 1 | 2,22 | 2,22
222 | 2014-10-11 | 333 | 1 | 3,33 | 3,33
222 | 2014-10-12 | 555 | 1 | 2,22 | 2,22
My query:
SELECT
CAST(Date AS DATE) as 'Data',
SUM(Qty*Price) AS 'Sum',
SUM(Qty) AS 'Qty'
FROM Table
WHERE ApID = 222
AND Data BETWEEN '2014-10-11' AND '2014-10-13'
AND Code LIKE '555'
GROUP BY CAST(KvitoGalva.Data AS DATE)
I get result like this:
Data | Sum | Qty
2014-10-11 | 4.44 | 2
2014-10-12 | 2.22 | 1
I need to display result in one table:
Data | Sum 555 | Qty 555 | Sum 333 | Qty 333 |
2014-10-11 | 4.44 | 2 | 3.33 | 1 |
2014-10-12 | 2.22 | 1 | 0 | 0 |
Tried:
SELECT((Select1),(Select2))
----------------------------
SELECT 1
union
select 2
You can do this using conditional aggregation:
SELECT CAST(Date AS DATE) as Data,
SUM(case when code = '555' then Qty*Price else 0 end) AS Sum555,
SUM(case when code = '555' then Qty else 0 end) AS Qty555,
SUM(case when code = '333' then Qty*Price else 0 end) AS Sum333,
SUM(case when code = '333' then Qty else 0 end) AS Qty333
FROM Table t
WHERE ApID = 222 AND
Data BETWEEN '2014-10-11' AND '2014-10-13' AND
Code IN ('555', '333')
GROUP BY CAST(KvitoGalva.Data AS DATE);
Note: only use single quotes for string and date constants. You do not need quotes for column aliases and if you did, then your database would have a better character for escaping the names.
need help for below.
Table1
+------------+-------------------+----------+
| Shipmnt | Costtype | cost |
+------------+-------------------+----------+
|22 | toll | 100 |
|23 | parking | 111 |
|25 | tax | 25 |
+------------+-------------------+----------+
Expected Result
+----------+--------+-----------+-------+
| shipmnt | toll | parking | tax |
+----------+--------+-----------+-------+
| 22 | 100 | 0 | 0 |
| 23 | 0 | 111 | 0 |
| 25 | 0 | 0 | 25 |
+----------+--------+-----------+-------+
i m trying to use case when but not able to get column.
You didn't state your DBMS, the following is standard SQL and works on all DBMS I know of.
select shipmt,
sum(case when costtype = 'toll' then cost end) as toll_costs,
sum(case when costtype = 'parking' then cost end) as parking_costs,
sum(case when costtype = 'tax' then cost end) as tax_costs
from shipments
group by shipmt;
Select distinct a.shipment,
ISNULL((Select cost from Table1 where Costtype='troll' and shipmnt=a.shipmnt),0) as troll,
ISNULL((Select cost from Table1 where Costtype='parking' and shipmnt=a.shipmnt),0) as parking,
ISNULL((Select cost from Table1 where Costtype='tax' and shipmnt=a.shipmnt),0) as tax
from Table1 a
QUERY
SELECT shipmnt,
MAX(IF(costType='toll',cost,0)) AS toll,
MAX(IF(costType='parking',cost,0)) AS parking,
MAX(IF(costType='tax',cost,0)) AS tax
FROM tbl1
GROUP BY shipmnt;
FIND FIDDLE HERE