To select multiple selects with different wheres I used:
SELECT table1.IDvar,
(CASE WHEN table2.var1 = 'foo' THEN table2.var2 END) AS condition1,
(CASE WHEN table2.var1 = 'bar' THEN table2.var2 END) AS condition2
FROM table1
FULL JOIN table2 ON table1.IDvar = table2.table1_IDvar
Unfortunately, this returns multiple rows per ID rather than containing each select column alias in different columns in the same row:
IDvar
condition1
condition2
x1
2
(null)
x1
(null)
(null)
x1
(null)
33
h2
1000
(null)
h2
(null)
(null)
h2
(null)
(null)
z3
(null)
0
z3
300
(null)
z3
(null)
(null)
Note: each ID value does not appear with an equal number of rows.
How do I return results of different (CASE WHEN END) AS x (or similar filtering concept) expressions in the same row per unique ID? An ouput something like this:
IDvar
condition1
condition2
x1
2
33
h2
1000
(null)
z3
300
0
The operation you're attempting to do is called "pivot" and follows two steps:
conditional selection through a CASE expression for each kind of field you want to extract
aggregation on a field for which we have separated information
Your query is fine, it's just missing the second step.
SELECT table1.IDvar,
MAX(CASE WHEN table2.var1 = 'foo' THEN table2.var2 END) AS condition1,
MAX(CASE WHEN table2.var1 = 'bar' THEN table2.var2 END) AS condition2
FROM table1
FULL JOIN table2 ON table1.IDvar = table2.table1_IDvar
GROUP BY table1.IDvar
Related
I have a dataset that I want to sum the values for by category (item), however before I sum them together I need to convert the currency of some values dependent on the currency in another column.
Sample dataset:
Item Currency Value
1 USD 10
1 PHP 100
2 USD 50
2 PHP 1000
3 PHP 500
select ITEM,
(case when CURRENCY='usd' then sum(VALUE*2) else sum(VALUE) end ) VALUE
from TABLE1
inner join TABLE2 on TABLE1.ID=TABLE2.ID
inner join TABLE3 on TABLE3.X=TABLE1.X
inner join TABLE4 on TABLE1.Y=TABLE4.Y
where A=1 and B=2 and C=5
group by ITEM, CURRENCY
ORDER BY ITEM asc
Desired outcome (using x2 as a factor to go from USD to PHP):
Item Value
1 120
2 1100
3 500
However, I am getting the following, which has correctly converted the currency, but is not grouping by item (ie. i'm getting duplicated rows for item rather than 1 row with the summed value):
Item Value
1 20
1 100
2 100
2 1000
3 500
The case should be the argument to the SUM():
select ITEM,
sum(case when CURRENCY='usd' then VALUE*2 else VALUE
end ) as VALUE
from TABLE1 join
TABLE2
on TABLE1.ID = TABLE2.ID join
TABLE3
on TABLE3.X = TABLE1.X join
TABLE4
on TABLE1.Y = TABLE4.Y
where A = 1 and B = 2 and C = 5
group by ITEM
ORDER BY ITEM asc;
Note: The GROUP BY is only by ITEM, because that defines the rows you want in the result set.
I have table with column 1 same for client and column 2 has different value , if I find a column 2 with a value then all the records for the client should not show in my results
Column 1 Column2
1
2
3
In the above if I use where column2=1 then I should not have all the records
Basically I want to skip 123 if column 2 has 1
SELECT * FROM your_table WHERE Column1 <> '123' AND Column2 = 1
UPDATED with Join Condition
SELECT your_table.* FROM your_table
INNER JOIN clients ON your_table.Column1 = clients.NAME
WHERE your_table.Column2 = 1
AND clients.NAME <> 'abc'
I have to tables :
Table1
--------------------------------
ID VAL1 DATE1
--------------------------------
1 1 20/03/2015
2 null null
3 1 10/01/2015
4 0 12/02/2015
5 null null
Table2
--------------------------------
ID VAL2 DATE1
--------------------------------
1 N 02/06/2015
1 N 01/08/2015
2 null null
3 O 05/04/2016
3 O 02/02/2015
4 O 01/07/2015
5 O 03/02/2015
5 N 10/01/2014
5 O 12/04/2015
I want to update :
column VAL1 (of Table1) with '0', if VAL2 (of Table2) is equal to 'O'
column DATE1 (of Table1) with the earliest DATE2 (of Table2) for each ID (here my problem)
(This two tables are not so simple, it's just for illustration, they can be joined with the ID column).
Here my code :
UPDATE Table1 t1
SET t1.VAL1 = '0',
t1.DATE1 = (select min(t2.DATE2) --To take the first DATE for each ID where VAL2='O' (not working fine)
FROM Table2 t2, Table1 t1
WHERE trim(t2.ID) = trim(t1.ID)
AND VAL2='O')
WHERE EXISTS (SELECT NULL
FROM Table2 t2
WHERE trim(t2.ID) = trim(t1.ID)
AND t2.Table2 = 'O')
AND VAL1<>'0'; --(for doing the update only if VAL1 not already equal to 0)
The expected result is :
Table1
--------------------------------
ID VAL1 DATE1
--------------------------------
1 1 20/03/2015
2 null null
3 0 02/02/2015
4 0 01/07/2015
5 0 10/01/2014
The result I get is :
Table1
--------------------------------
ID VAL1 DATE1
--------------------------------
1 1 20/03/2015
2 null null
3 0 10/01/2014
4 0 10/01/2014
5 0 10/01/2014
My problem is that the DATE1 is always updated with the same date, regardless of the ID.
You shouldn't have a second reference to table1 in the first subquery; that is losing the correlation between the subquery and the outer query. If you run the subquery on its own it will always find the lowest date in table2 for any ID that has val2='O' in table1, which is 10/01/2014. (Except your sample data isn't consistent; that's actually N so won't be considered - your current and expected results don't match the data you showed, but you said it isn't real). Every row eligible to be updated runs that same subquery and gets that same value.
You need to maintain the correlation between the outer query and the subquery, so the subquery should use the outer table1 for its join, just like the second subquery already does:
UPDATE Table1 t1
SET t1.VAL1 = '0',
t1.DATE1 = (select min(t2.DATE2)
FROM Table2 t2
WHERE trim(t2.ID) = trim(t1.ID)
AND VAL2='O')
WHERE EXISTS (SELECT NULL
FROM Table2 t2
WHERE trim(t2.ID) = trim(t1.ID)
AND t2.Val2 = 'O')
AND VAL1<>'0';
You can use this UPDATE statement.
UPDATE TABLE1 T1
SET T1.VAL1 = '0',
T1.DATE1 = (SELECT MIN(T2.DATE2)
FROM TABLE2 T2
WHERE TRIM(T2.ID) = TRIM(T1.ID)
AND T2.VAL2='O')
WHERE T1.ID IN (SELECT T2.ID FROM TABLE2 T2 WHERE T2.VAL2='O')
Hope it will help you.
MYSQL Solution
Hope this MySql syntax also works with ORACLE.
The issue with the SQL is that it only consider the records with VAL2=='O' when calculating the earliest date. So the last record have the date as shown in table below. Record "5 N 10/01/2014" is not considered.
UPDATE Table1, (SELECT * FROM (SELECT * FROM table2 WHERE VAL2='O' ORDER BY ID, DATE1) X GROUP BY X.ID) T2
SET Table1.DATE1=T2.DATE1, Table1.VAL1=0
WHERE Table1.ID=T2.ID
..
Table1
--------------------------------
ID VAL1 DATE1
--------------------------------
1 1 20/03/2015
2 null null
3 0 02/02/2015
4 0 01/07/2015
5 0 **03/02/2015**
Tested on MySql 5.6.14
I have a question on SQL join which involve multiple condition in second joined table. Below is the table details
Table 1
pId status keyVal
---- ------- ------
100 1 45
101 1 46
Table 2
pId mode modeVal
100 2 5
100 3 6
101 2 7
101 3 8
I have above two tables and I am trying to join based on below condition to get pId's
pId's which has keyVal = 45 and status = 1 joined with table2 which has mode = 2 and modeVal 5 and mode =3 and modeVal = 6
the result I am expecting is to return pid = 100
Can you please help me with a join query ?
One way is to use GROUP BY with HAVING to count that the number of rows found is 2, of which 2 are matching the condition;
WITH cte AS (SELECT DISTINCT * FROM Table2)
SELECT t1."pId"
FROM Table1 t1 JOIN cte t2 ON t1."pId" = t2."pId"
WHERE t1."status" = 1 AND t1."keyVal" = 45
GROUP BY t1."pId"
HAVING SUM(
CASE WHEN t2."mode"=2 AND t2."modeVal"=5 OR t2."mode"=3 AND t2."modeVal"=6
THEN 1 END) = 2 AND COUNT(*)=2
If the values in t2 are already distinct, you can just remove the cte and select directly from Table2.
An SQLfiddle to test with.
SELECT columns
FROM table1 a, table2 B
WHERE a.pid = B.pid
AND a.keyval = 45
AND a.status = 1
AND (
(B.mode = 2 AND B.modeval = 5)
OR
(B.mode = 3 AND B.modeval = 6)
)
Below query should work for you perfectly
select distinct table1.pid FROM table1 JOIN table2
on table1.pid = table2.pid
WHERE table2.modeValue IN (5,6) AND table2.mode IN (2,3) AND table1.keyVal=45 and table1.status=1;
From this table
D_value
-------
A
B
B
C
C
C
To display count D_Value into this table
A | B | C
---------
1 | 2 | 3
To get a single row, use this.
SELECT
COUNT(CASE WHEN D_Value = 'A' THEN 1 END) AS A,
COUNT(CASE WHEN D_Value = 'B' THEN 1 END) AS B,
COUNT(CASE WHEN D_Value = 'C' THEN 1 END) AS C
FROM
MyTable
This works for a finite and fixed number of values to count
If you do not know how many different values, then you need to do a simple aggregate and make a single row in the client code.
SELECT D_value, COUNT(*) FROM MyTable GROUP BY D_value;
However, this won't give zero counts for values that do not exist. So you'd need a lookup table and LEFT JOIN. I won't go there yet...
select D_value,count(*) from table group by D_value;