I'm using Oracle SQL and i need a help with a query.
I need to count how many rows have at least one value of NA.
My table have more than 300 columns (these are not the real columns names):
col1 varchar,
col2 varchar,
col3 varchar,
...
...
...
col300 varchar
Here is an example of a table:
col1 | col2 | col3 | col4
10 | 15 | 55 | NA
NA | 15 | 55 | NA
10 | 15 | 55 | 33
10 | NA | 55 | 58
10 | 15 | 55 | 33
10 | 15 | 55 | 84
10 | 15 | NA | 40
Output expected result: 4
Please advise.
You can do a Sum of a sub select using a case to get this:
Select SUM(NA)
From
(Select case when col1 = 'NA' then 1 case when col2 = 'NA' then 1 case when col3 = 'NA' then 1 case when col4 = 'NA' then 1 end as NA
from Table) a
Use count
SELECT
COUNT(1)
FROM
table_name
WHERE
'NA' IN (col1, col2, ..., col300)
Well, I've found the solution.
select sum(cnt) from
(
select case when
col1 = 'NA'
or col2 = 'NA'
or col3 = 'NA'
or col4 = 'NA' then 1 end cnt
from MyTable
)
Related
I have two tables: table1 and table2 (The tables are almost identical, table2 has an extra field. 30 columns in table1, and 31 columns in table2. the extra column is a key).
I also have a procedure, which gets a number at first. If the number is above 10, I want to isnert the row in all the 30 columns from table1 to table2. Otherwise, I want to insert columns 1 to 20 (from table1), and insert columns 20-30 multiplied by 30. I have created two different "INSERT INTO TABLE" for each situation (above/under 10), but I belive there is more efficient way, since the first 20 rows should be the same in every case. I thought to insert first the first 20 rows, and after enter "IF" statement and then 'insert' according to the given parameter the remain columns. But ofcourse I'm getting two rows instead of one.
what is the solution, so I will insert all the data into one row?
Here is an example with 10 columns (instead of 30). In this example, if the paramter is above 10, we'll insert the row as is into table2. otherwise, we will insert col1-col7, and multiply col8-col10.
parameter = 15
table1
Col1 | Col2 | Col3 | Col4 | Col5 | Col6 | Col7 | Col8 | Col9 |Col10 |
======+======+======+======+======+======+======+======+======+======+
1 | 1 | 1 | 2 | 2 | 2 | 2 | 5 | 5 | 5 |
table2 (Identical to table 1, because the parameter > 10 )
Col1 | Col2 | Col3 | Col4 | Col5 | Col6 | Col7 | Col8 | Col9 |Col10 |
======+======+======+======+======+======+======+======+======+======+
1 | 1 | 1 | 2 | 2 | 2 | 2 | 5 | 5 | 5 |
If the parameter was parameter = 3 , then table two was:
table2 (columns 8-10 multiplied)
Col1 | Col2 | Col3 | Col4 | Col5 | Col6 | Col7 | Col8 | Col9 |Col10 |
======+======+======+======+======+======+======+======+======+======+
1 | 1 | 1 | 2 | 2 | 2 | 2 | 150 | 150 | 150 |
A template to my code:
if #Parameter >10
begin
INSERT INTO Table1
(Col1
,Col2
,Col3
...
,Col29
,Col30)
SELECT
Col1
,Col2
,Col3
...
,Col29
,Col30
FROM ...
wHERE ...
end
else
begin
INSERT INTO Table1
(Col1
,Col2
,Col3
...
,Col29
,Col30)
SELECT
Col1
,Col2
,Col3
...
,Col29
,Col30
FROM ...
wHERE ...
end
Right now I have more then 120 lines, when 2/3 from them are duplicated.
How can I make it more efficient?
As far as I could your problem you could use,INSERT ALL COMMAND
FOR eg:-
INSERT ALL
WHEN number>10 THEN
INTO table1 VALUES(col1,col2,col3)
INTO table1 VALUES(col1,col2,col3)
WHEN number<10
INTO table1 VALUES(col1,col2,col3)
INTO table1 VALUES(col1,col2,col3)
select * from dual
use condition as per your requirement
We use software to store combinations of financial elements. Those elements are allowed in certain combinations. Exceptions of these combinations are SQL-like statements in the front-end, and are saved as numerical values in a database table like the following example:
+------+------+------+------+------+
| Col1 | Col2 | Col3 | Col4 | Col5 |
+------+------+------+------+------+
| 1 | 2 | 4 | 5 | 1 |
+------+------+------+------+------+
| -1 | 2 | 6 | 4 | 5 |
+------+------+------+------+------+
| 1 | 2 | 5 | 7 | 1 |
+------+------+------+------+------+
I would like to translate those numerical values back to a SQL-statement like the following example:
+------+-----------+------+-----------+------+-----------+------+-----------+------+-----------+
| Col1 | Col1Trans | Col2 | Col2Trans | Col3 | Col3Trans | Col4 | Col4Trans | Col5 | Col5Trans |
+------+-----------+------+-----------+------+-----------+------+-----------+------+-----------+
| 1 | ( | 2 | SELECT | 4 | CODE | 5 | LIKE | 1 | * |
+------+-----------+------+-----------+------+-----------+------+-----------+------+-----------+
| -1 | | 2 | SELECT | 6 | NUMBER | 4 | = | 5 | AND |
+------+-----------+------+-----------+------+-----------+------+-----------+------+-----------+
| 1 | ( | 2 | SELECT | 5 | TOOL | 7 | <> | 1 | * |
+------+-----------+------+-----------+------+-----------+------+-----------+------+-----------+
The numerical values differ in each column so I can only imagine the use of a lot of case...when statements which I doubt will be efficiƫnt. I don't want to create tables to hold the translation values. Are there ways to do this with arrays?
Are there any code samples to easily loop through table/columns and translate the contents of it?
You can use below code and add more case statement as per the requirement.
SELECT Col1
,CASE
WHEN Col1 = 1 THEN '('
ELSE '' END AS Col1Trans
,Col2
,CASE
WHEN Col2 = 2 THEN 'SELECT'
END AS Col2Trans
,Col3
,CASE
WHEN Col3 = 4 THEN 'CODE'
WHEN Col3 = 6 THEN 'NUMBER'
WHEN Col3 = 5 THEN 'TOOL'
END AS Col3Trans
,Col4
,CASE
WHEN Col4 = 5 THEN 'LIKE'
WHEN Col4 = 4 THEN '='
WHEN Col4 = 7 THEN '<>'
END AS Col4Trans
,Col5
,CASE
WHEN Col5 = 1 THEN '*'
WHEN Col5 = 5 THEN 'AND'
END AS Col5Trans
The best way to avoid so many case when and decode and etc is to use with as clause as following:
With col1trans (value, translation) as
(Select 1, '(' from dual union all
Select -1, null from dual),
Col2trans (value, translation) as
(Select 2, 'SELECT' from dual)
..
... till col5trans
Select m.col1, t1.translation as col1trans,
.... till m.col5, t5.translation
From your_table m join col1trans t1 m.col1=t1.value
join col2trans t2 m.col2=t2.value
... till col5trans
Cheers!!
I have got a query which result is in table1
-------------------------
|column1|column2|column3|
-------------------------
| v1 | 30 | 40 |
| v1 | 34 | 41 |
| v1 | 35 | 42 |
| v2 | 30 | 40 |
| v2 | 34 | 41 |
| v2 | 35 | 42 |
-------------------------
I want to change duplicated values to NULL in first column, (i.e).
-------------------------
|column1|column2|column3|
-------------------------
| v1 | 30 | 40 |
| null | 34 | 41 |
| null | 35 | 42 |
| v2 | 30 | 40 |
| null | 34 | 41 |
| null | 35 | 42 |
-------------------------
What should I do with table1?
You can use row_number() function:
select (case when row_number() over (partition by col1 order by col1) > 1
then null else col1 end) col1,
col2, col3
from table t;
However, you can also use lag() function
select (case when lag(col1) over (partition by col1 order by col1) = col1
then null else col1 end) col1,
col2, col3
from table t;
try this:
SELECT CASE WHEN D.RN = 1 THEN column1 ELSE NULL END AS column1
,column2
,column3
FROM(
SELECT *
, ROW_NUMBER() OVER(PARTITION BY column1 ORDER BY column1)RN
FROM Your_table
)D
You can try this query.
using ROW_NUMBER function to make rowNumber,then CASE When Expression to show the first column1 else be null
ORDER BY (SELECT 1) can let your data be the original order.
select CASE WHEN rn = 1 THEN column1 ELSE NULL END,
column2,
column3
from
(
SELECT column1,
column2,
column3,
ROW_NUMBER() OVER(PARTITION BY column1 ORDER BY (SELECT 1)) rn
FROM T
) t
sqlfiddle:http://sqlfiddle.com/#!15/fcf3d/1
SELECT CASE WHEN RN=1 THEN
"column1"
ELSE
NULL
END AS "column1",
"column2", "column3"
FROM
(
SELECT
"column1", "column2", "column3",
ROW_NUMBER() OVER (PARTITION BY "column1" ORDER BY "column1") AS RN
FROM Table1
) AS T
Ouput
column1 column2 column3
v1 30 40
(null) 34 41
(null) 35 42
v2 30 40
(null) 34 41
(null) 35 42
Demo
http://sqlfiddle.com/#!17/5b2e1/9
I have a table that looks like this:
| col1 | col2 |
|------|------|
| a | 1 |
| a | 2 |
| a | 3 |
| b | 1 |
| b | 3 |
| c | 1 |
| c | 2 |
I need to find the value of col1 where two rows with the same col1 value exist that has a col2 value of 1 and 2
results would be:
| col1 |
|------|
| a |
| c |
You can filter the rows with the col2 values you want, then group by col1 and only take the groups with count = 2
select col1
from yourTable
where col2 in (1, 2)
group by col1
having count(distinct col2) = 2
Another solution would be
select col1
from your_table
group by col1
having sum(case when col2 = 1 then 1 else 0 end) > 0
and sum(case when col2 = 2 then 1 else 0 end) > 0
I have a table that looks like the first example.
I'm trying to write a MSSQL2012 statement that that will display results like the second example.
Basically I want null values instead of duplicate values in columns 1 and 2. This is for readability purposes during reporting.
This seems like it should be possible, but I'm drawing a blank. No amount of joins or unions I've written has rendered the results I need.
| Col1 | Col2 | Col3 |
+------+------+------+
| 1 | 2 | 4 |
| 1 | 2 | 5 |
| 1 | 3 | 6 |
| 1 | 3 | 7 |
+------+------+------+
| Col1 | Col2 | Col3 |
+------+------+------+
| 1 | 2 | 4 |
| Null | null | 5 |
| null | 3 | 6 |
| null | null | 7 |
+------+------+------+
I would do this with no subqueries at all:
select (case when row_number() over (partition by col1 order by col2, col3) = 1
then col1
end) as col1,
(case when row_number() over (partition by col2 order by col3) = 1
then col2
end) as col2,
col3
from t
order by t.col1, t.col2, t.col3;
Note that the order by at the end of the query is very important. The result set that you want depends critically on the ordering of the rows. Without the order by, the result set could be in any order. So, the query might look like it works, and then suddenly fail one day or on a slightly different set of data.
Using a common table expression with row_number():
;with cte as (
select *
, rn_1 = row_number() over (partition by col1 order by col2, col3)
, rn_2 = row_number() over (partition by col1, col2 order by col3)
from t
)
select
col1 = case when rn_1 > 1 then null else col1 end
, col2 = case when rn_2 > 1 then null else col2 end
, col3
from cte
without the cte
select
col1 = case when rn_1 > 1 then null else col1 end
, col2 = case when rn_2 > 1 then null else col2 end
, col3
from (
select *
, rn_1 = row_number() over (partition by col1 order by col2, col3)
, rn_2 = row_number() over (partition by col1, col2 order by col3)
from t
) sub
rextester demo: http://rextester.com/UYA17142
returns:
+------+------+------+
| col1 | col2 | col3 |
+------+------+------+
| 1 | 2 | 4 |
| NULL | NULL | 5 |
| NULL | 3 | 6 |
| NULL | NULL | 7 |
+------+------+------+