Table1' Sample data:
ID value1 Value2 value3
001 10 20 30
002 20 10 null
003 10 null null
004 10 null 30
....
From the table1, I want to make a coulmn count.
Count of row query
Select count(*) from table1 'It will give only row count.
But i need column count, which column value should not be null
Expected output
ID | totcolumn
-----------------
001 3
002 2
003 1
004 2
....
How to make a query, need query help
Use SUM as follows:
SELECT id,
SUM(CASE WHEN value1 IS NULL then 0 ELSE 1 END) +
SUM(CASE WHEN value2 IS NULL then 0 ELSE 1 END) +
SUM(CASE WHEN value3 IS NULL then 0 ELSE 1 END) AS 'COUNT'
FROM table1
group by id
DEMO
This is a nice opportunity to use UNPIVOT if you are on MS SQL Server 2005 or later. First set up some sample data:
create table ColumnCount (
ID char(3) not null,
Value1 int,
Value2 int,
Value3 int
)
insert into ColumnCount(ID,Value1,Value2,Value3)
select '001',10,20,30
union all select '002',20,10,null
union all select '003',10,null,null
union all select '004',10,null,30
union all select '005',null,null,null
I added 005 to the sample data you provided above, to show how to handle the case where all ValueX columns are null.
UNPIVOT "normalizes" the data for you so that you can use COUNT against the rows:
select *
from ColumnCount
unpivot (Value for ValueN in (Value1, Value2, Value3)) as upvt
ID Value ValueN
001 10 Value1
001 20 Value2
001 30 Value3
002 20 Value1
002 10 Value2
003 10 Value1
004 10 Value1
004 30 Value3
Notice that it eliminated the NULL values already, so you do not have to. Unfortunately this means that rows with NULL in all ValueX columns (e.g., ID='005') will not show up if you do a simple count. Instead, gather all ID's in a subquery or CTE like AllIds below:
with ColumnsOnRows as (
select *
from ColumnCount
unpivot (Value for ValueN in (Value1, Value2, Value3)) as upvt
),
AllIds as (
select distinct ID
from ColumnCount
)
select AllIds.ID, count(distinct Value) as totcolumn
from AllIds
left outer join ColumnsOnRows
on ColumnsOnRows.ID = AllIds.ID
group by AllIds.ID
Result:
ID totcolumn
001 3
002 2
003 1
004 2
005 0
If I understand you correctly what you need is something like this
SELECT ISNULL(Value1, 0) + ISNULL(Value2, 0) + ISNULL(Value3, 0) AS _Sum FROM table1
ISNULL will replace the value with 0 if it is NULL
Related
Here, I have these records:
ID
Value1
Value2
1
30
50
1
32
50
2
20
60
2
20
65
3
10
70
And the aim was to find the sum of matching ID's Value1s and for the Value2, find the sum of only non-matching records and others would stay as they were before.
Like here:
ID
Value1
Value2
1
62
50
2
40
125
3
10
70
…
declare #t table(id int,val1 int,val2 int);
insert into #t(id,val1,val2)
values(1,30,50),(1,32,50),(2,20,60),(2,20,65),(3,10,70);
select id, sum(val1) as val1, sum(distinct val2) as val2
from #t
group by id;
This seems like some odd logic, if I am honest. You could, however, use a CTE with some row numbering, followed by some conditional aggregation:
WITH CTE AS(
SELECT ID,
Value1,
Value2,
ROW_NUMBER() OVER (PARTITION BY ID, Value2 ORDER BY (SELECT NULL)) AS RN --Which row is arbitrary as it doesn't matter
FROM dbo.YourTable)
SELECT ID,
SUM(Value1) AS Value1,
SUM(CASE RN WHEN 1 THEN Value2 END) AS Value2
FROM CTE
GROUP BY ID
ORDER BY ID;
I have the current situation:
TableA
----------
SN Date OpsID
1234 2018-02-12 1
1324 2018-02-12 2
2134 2018-02-13 3
TableB
----------
Name String Number OpsID
Value1 Hello NULL 1
Value2 NULL 1111 1
Value3 Apples NULL 1
Value1 There NULL 2
Value2 NULL 2222 2
Value3 Pears NULL 2
Value1 Baby NULL 3
Value2 NULL 3333 3
Value3 Bananas NULL 3
...and the result I'm looking for is:
SN Date Value1 Value2 Value3
1234 2018-02-12 Hello 1111 Apples
1324 2018-02-12 There 2222 Pears
2134 2018-02-13 Baby 3333 Bananas
The query I ran is obviously wrong because I'm getting mostly NULL and only Value data, but here it is anyway:
SELECT SN,Date,Value1,Value2,Value3
FROM(
SELECT TableA.SN,
TableA.Date,
TableB.Name,
TableB.String,
TableB.Number
FROM TableA,TableB
WHERE
TableA.OpsID = TableB.OpsID
ORDER BY Date ASC
)Temp
PIVOT(
MAX(Value)
FOR Name in(
Value1,Value2,Value3
)
)PIV
Note that Value1 and Value3 are always VARCHAR and Value2 is always an INT
You combine String and Number into a single column in a subquery, and then pivot the values back out into their own columns like this:
SELECT SN, Date, Value1, CAST(Value2 AS INT) Value2, Value3
FROM
(
SELECT a.SN, a.Date, B.Name, ISNULL(b.String, CAST(b.Number AS VARCHAR(10))) Value
FROM TableA A
INNER JOIN TableB B ON A.OpsID = B.OpsID
)sq1
PIVOT (MAX(Value) FOR Name IN ([Value1], [Value2], [Value3]))sq2
You can do conditional aggregation :
select a.SN, a.date,
max(case when b.Name = 'Value1' then coalesce(b.String, cast(b.Number as varchar(255))) end) as Value1,
max(case when b.Name = 'Value2' then coalesce(b.String, cast(b.Number as varchar(255))) end) as Value2,
max(case when b.Name = 'Value3' then coalesce(b.String, cast(b.Number as varchar(255))) end) as Value3
from tablea a inner join
tableb b
on b.OpsID = a.OpsID
group by a.SN, a.date;
I have requirement to update column3 of following table by cross checking the value of value2 with next row of value1
If equal then value3 = value1*value2 and if not value3 = value1
CREATE TABLE #tmpValue1(id INT IDENTITY(1,1), value1 FLOAT, value2 FLOAT, value3 FLOAT)
INSERT INTO #tmpValue1(value1, value2) VALUES
(1, 2), (2,3), (3,4), (4,5),(6,7),(7,8),(8,9)
Table #tmpValue1 will be as:
id value1 value2 value3 (expected output)
1 1 2 1
2 2 3 4
3 3 4 9
4 4 5 16
5 6 7 6
6 7 8 49
7 8 9 64
Above, in value3 updated with 1 in first because 2 of Value2 row first is comparing to 2 of value1 of row second so it will start updating with second.
Note: Value1 and Value2 is just sample and is real it can be different.
We can simply do it by using LEFT JOIN as below:
UPDATE t1 SET t1.value3 = (ISNULL(t2.value2,1) * t1.value1)
FROM #tmpValue1 t1
LEFT JOIN #tmpValue1 t2 ON t1.id = t2.id+1
AND t1.value1 = t2.value2
We should use id which is identity column and is beneficial for performing such an operation.
You can use LAG... though your expected output seems to have some errors in it.
select
ID,
Value1,
Value2,
case
when lag(value2) over (order by ID) = value1 then lag(value2) over (order by ID) * value1
else value1 end as Value3
from #tmpValue1
RESULTS
ID Value1 Value2 Value3
1 1 2 1
2 2 3 4
3 3 4 9
4 4 5 16
5 6 7 6
6 7 8 49
7 8 9 64
First sorry for my bad english it's not my native language :(
I'm kinda new in Oracle and I need help with following. I have several records with same ID, several values (which can be same) and different creation date.
I would like to select an ordinal number for IDs which have same value, but different date.
For example
ID | Value | Date | Number
A | Value1 | 01.11. | 1
A | Value1 | 02.11. | 2
A | Value2 | 03.11. | null
A | Value2 | 01.11. | null
B | Value1 | 01.11. | 1
B | Value1 | 03.11. | 2
B | Value2 | 01.11. | null
C | Value1 | 01.11. | 1
C | Value2 | 01.11. | null
So for every ID in first coloumn where I have Value1 I want to have increment and for the rest of the values I don't need to have anything.
I hope I'm not posting double question I have tried to look it up, but I couldn't find any answer.
Thank you in advance!
Edit: Will accept one instead of null for other values.
The basic idea is row_number() to get the sequential value and rank() to rank the values. You only want the first set to be enumerated. "First" corresponds to rank() having a value of 1. The rest get NULL:
select id, value, date,
(case when rank() over (partition by id order by value) = 1
then row_number() over (partition by id order by value)
end) as number
from table t;
EDIT:
I realize that you might actually want the first value by time and not some other ordering. For that, use keep instead of rank():
select id, value, date,
(case when value = max(value) keep (dense_rank first order by value) over (partition by id)
then row_number() over (partition by id order by value)
end) as number
from table t;
Hmm... Hope I understood correctly:
with my_table as (
select 'A' ID, 'Value1' value, '01.11.' dt, 1 num from dual union all
select 'A', 'Value1', '02.11.', 2 from dual union all
select 'A', 'Value2', '03.11.', null from dual union all
select 'A', 'Value2', '01.11.', null from dual union all
select 'B', 'Value1', '01.11.', 1 from dual union all
select 'B', 'Value1', '03.11.', 2 from dual union all
select 'B', 'Value2', '01.11.', null from dual union all
select 'C', 'Value1', '01.11.', 1 from dual union all
select 'C', 'Value2', '01.11.', null from dual)
select *
from (select t.*, count(distinct dt) over (partition by value, id) diff_cnt
from my_table t) tt
where tt.diff_cnt > 1;
result:
ID VALUE DT NUM DIFF_CNT
-- ------ ------ ---------- ----------
A Value1 01.11. 1 2
A Value1 02.11. 2 2
B Value1 01.11. 1 2
B Value1 03.11. 2 2
A Value2 01.11. 2
A Value2 03.11. 2
I know this might seem a bit strange but I want to build a stored procedure that returns some values but I want the first row to be a null value. What I have for the query and returns are
SELECT CONCAT(id, ' ', item)As DisplayBox, id, item FROM table
DisplayBox id expense
1 Value2 1 Value2
2 Value3 2 Value3
3 Value4 3 Value4
4 Value5 4 Value5
But I am interested in having a result like
DisplayBox id Item
<BlankText> Null <BlankText>
1 Value2 1 Value2
2 Value3 2 Value3
3 Value4 3 Value4
4 Value5 4 Value5
You can use UNION ALL:
SELECT NULL AS DisplayBox, NULL AS id, NULL AS item
UNION ALL
SELECT CONCAT(id, ' ', item)As DisplayBox, id, item FROM table
SELECT null as displaybox, null as id, null as item from dual
union all
SELECT CONCAT(id, ' ', item)As DisplayBox, id, item FROM table
order by (case when id is null then 0 else 1 end)