SQL Select row depending on values in different columns - sql

I've already found so many answers here but now I can't seem to find any to my specific problem.
I can't figure out how to select a value from a row depending on the value in different columns
with the below table, I want to achieve the following results.
in case the value in column stdvpuni = 1 then return values / contents from this row for the article (column art).
in case the value in column stdvpuni = 0 then return values / contents from the row where STDUNIABG = 1 for this article (column art).

You seem to want one row part art, based on the content of other rows. That suggests using row_number():
select t.*
from (select t.*,
row_number() over (partition by art order by stdvpuni desc, STDUNIABG desc) as seqnum
from t
) t
where seqnum = 1;
You don't specify what to do if neither column is 1. You might want a where clause (where 1 in (stdvpuni, STDUNIABG)) or another condition in the order by.

I do not know what values / contents is, but I suppose that's easy for you to figure out. So, I will focus on the way to select this:
SELECT
CASE
WHEN current.stdvpuni = 1 THEN 'values / contents of current row'
ELSE 'values / contents of other row'
END
FROM yourtable current
JOIN yourtable other
ON other.stdvpuni = 1;

Use your conditions with NOT EXISTS in the WHERE clause:
SELECT t1.*
FROM tablename t1
WHERE t1.STDVPUNI = 1
OR (
t1.STDVPUNI = 0 AND t1.STDUNIABG = 1
AND NOT EXISTS (SELECT 1 FROM tablename t2 WHERE t2.ART = t1.ART AND t2.STDVPUNI = 1)
);

Related

Finding rows in SQL where changes but only certain changes while keeping others

I have this scenario where I want each occurrence of an active row to bring back that row in my result set and also inactive if there is only 1 inactive record for that IDENTIFIER and also if there are more than 1 active also show those. I've used Row_Number function and then in another query show where the row = '1' but if I do that row 1s only come back and then I lose some of my desired results. To restate my issue is I want all active records to come back and only inactive where IDENTIFIER is unique. The row that is bold should not be shown in the results.
1 has 1 active record in the DB.
2 has 2 active and 1 inactive records.
3 has no active records.
4 has only 2 active records, no inactive.
You can use a windowed conditional count, this has the benfit of only scanning the table once
SELECT
t.IDENTIFIER,
t.DB_ID,
t.Status
FROM (
SELECT *,
HasActive = COUNT(CASE WHEN t.Status = 'Active' THEN 1 END) OVER (PARTITION BY t.IDENTIFIER)
FROM YourTable t
) t
WHERE t.Status = 'Active' OR t.HasActive = 0;
One way to do this is with NOT EXISTS:
SELECT t1.*
FROM tablename t1
WHERE t1.Status = 'Active'
OR NOT EXISTS (
SELECT 1
FROM tablename t2
WHERE t2.identifier = t1.identifier AND t2.db_id <> t1.db_id
);
I assume that the column db_id is unique, at least for the same identifier.
If I understood you correctly, this is my variant.
select IDENTIFIER, [DB_ID], [Status]
from Tab
where [Status]='Active'
union
select IDENTIFIER, [DB_ID], [Status]
from Tab as t
where [Status]='Inactive' And 1=(select Count(*) from Tab where
IDENTIFIER=t.IDENTIFIER)
Order by IDENTIFIER, [DB_ID]
you can do it like this, because (rank=1 and Status=Inactive) only if there are no active rows for a particular Identifier
select * from (
select *,
DENSE_RANK() OVER (PARTITION BY identifier order by status) AS rank
from some_table
)
where rank=1 or status = 'Active'

Conditional view in oracle

Below is the table from which I need to create conditionalize view.
and I am getting one flag from different table. So based on the flag values i.e. if flag=1 then I need to display actual column values from table, and if flag=0 then show all column values as null values.
I know we can handle it using CASE statement but here, in may case column count is very big so need to handle it in better way.
You could try using a CASE expression along with REGEXP_REPLACE to mask the value column:
SELECT ID,
CASE WHEN flag = 1 THEN Value ELSE REGEXP_REPLACE(Value, '.', '*') END AS Value
FROM yourTable;
You can use left join:
select t.*
from (select 1 as flag from dual) x left join
t
on x.flag = :flag;
If :flag = 1, then all columns will be shown. If :flag is anything else, then all values will be NULL.
If you actually want to show the ids, it is a little more complicated:
select i.*, t.*
from (select 1 as flag from dual) x left join
(select id, . . . -- columns you want to keep
from t
) i left join
t
on x.flag = :flag and t.id = i.id;
You will probably need to list out the columns with the NULL values.

Create a new table with columns with case statements and max function

I have some problems in creating a new table from an old one with new columns defined by case statements.
I need to add to a new table three columns, where I compute the maximum based on different conditions. Specifically,
if time is between 1 and 3, I define a variable max_var_1_3 as max((-1)*var),
if time is between 1 and 6, I define a variable max_var_1_6 as max((-1)*var),
if time is between 1 and 12, I define a variable max_var_1_12 as max((-1)*var),
The max function needs to take the maximum value of the variable var in the window between 1 and 3, 1 and 6, 1 and 12 respectively.
I wrote this
create table new as(
select t1.*,
(case when time between 1 and 3 then MAX((-1)*var)
else var
end) as max_var_1_3,
(case when time between 1 and 6 then MAX((-1)*var)
else var
end) as max_var_1_6,
(case when time between 1 and 12 then MAX((-1)*var)
else var
end) as max_var_1_12
from old_table t1
group by time
) with data primary index time
but unfortunately it is not working. The old_table has already some columns, and I would like to import all of them and then compare the old table with the new one. I got an error that says that should be something between ) and ',', but I cannot understand what. I am using Teradata SQL.
Could you please help me?
Many thanks
The problem is that you have GROUP BY time in your query while trying to return all the other values with your SELECT t1.*. To make your query work as-is, you'd need to add each column from t1.* to your GROUP BY clause.
If you want to find the MAX value within the different time ranges AND also return all the rows, then you can use a window function. Something like this:
CREATE TABLE new AS (
SELECT
t1.*,
CASE
WHEN t1.time BETWEEN 1 AND 3 THEN (
MAX(CASE WHEN t1.time BETWEEN 1 AND 3 THEN (-1 * t1.var) ELSE NULL END) OVER()
)
ELSE t1.var
END AS max_var_1_3,
CASE
WHEN t1.time BETWEEN 1 AND 6 THEN (
MAX(CASE WHEN t1.time BETWEEN 1 AND 6 THEN (-1 * t1.var) ELSE NULL END) OVER()
)
ELSE t1.var
END AS max_var_1_6,
CASE
WHEN t1.time BETWEEN 1 AND 12 THEN (
MAX(CASE WHEN t1.time BETWEEN 1 AND 12 THEN (-1 * t1.var) ELSE NULL END) OVER()
)
ELSE t1.var
END AS max_var_1_12,
FROM old_table t1
) WITH DATA PRIMARY INDEX (time)
;
Here's the logic:
check if a row falls in the range
if it does, return the desired MAX value for rows in that range
otherwise, just return that given row's default value (var)
return all rows along with the three new columns
If you have performance issues, you could also move the max_var calculations to a CTE, since they only need to be calculated once. Also to avoid confusion, you may want to explicitly specify the values in your SELECT instead of using t1.*.
I don't have a TD system to test, but try it out and see if that works.
I cannot help with the CREATE TABLE AS, but the query you want is this:
SELECT
t.*,
(SELECT MAX(-1 * var) FROM old_table WHERE time BETWEEN 1 AND 3) AS max_var_1_3,
(SELECT MAX(-1 * var) FROM old_table WHERE time BETWEEN 1 AND 6) AS max_var_1_6,
(SELECT MAX(-1 * var) FROM old_table WHERE time BETWEEN 1 AND 12) AS max_var_1_12
FROM old_table t;

Create a flag value based on the duplicate values on one column in SQL

I am quite new to SQL. Playing around with it and got stuck in the following scenario.
I have a table with the following data
My requirement is, in the FirstCol column, it has '11121' 3 times, and SecondCol has 1001 two times against FirstCol and it has 1002 against the same '11121' value which should not be. If it exists that way, I need to find all the data in such scenarios and need to display a column beside these two columns with a flag value indicating 1 if the value in the SecondCol is different than the other values. '0' should be displayed for the remaining.
I tried using group by, dense_rank() but couldn't get the desired results. Someone please help me out in getting the desired result for this.
I think you want:
select t.*,
(case when min(col1) over (partition by col2) =
max(col1) over (partition by col2)
then 0 else 1
end) as flag
from t;
This flags all rows where col2 has multiple values in col1.
You can use EXISTS and a correlated subquery, that checks, if there are row with the same firstcol but with a different secondcol. Put that in a CASE returning 1 if such a record exists, 0 otherwise.
SELECT t1.firstcol,
t1.secondcol,
CASE
WHEN EXISTS (SELECT *
FROM elbat t2
WHERE t2.firstcol = t1.firstcol
AND t2.secondcol <> t1.secondcol) THEN
1
ELSE
0
END flag
FROM elbat t1;

Find the Row which contain only row with zero and One for the Particular data

I have data where group will one row as zero and one and for the same data value will give one and two.
I have tried with below code .which seems to be not working
select *
from (select livecasnum, flag,
DENSE_RANK()over (partition by livecasnum order by flag) as Ranks
from TblcaseFlag
group by livecasnum, flag
) b
group by livecasnum,flag,Ranks
having count(flag + Ranks) = 1 and flag <> 1
I need only like data one row which having only zero and one ex: 99149
Why not use not exists instead :
select tf.*
from TblcaseFlag tf
where tf.flag = 0 and
not exists (select 1
from TblcaseFlag tf1
where tf.livecasnum = tf1.livecasnum and
tf1.flag = 1
);