Create a flag value based on the duplicate values on one column in SQL - 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;

Related

display a value only if none of the dependent values are nul

I am quite new to SQL and would need some suggestions to write a query to select the value of Col1 only if none of the value of status of Col2 (Col3) is null in plsql.
In the above, I am expecting the result to return only A2 as in A1, there is a null value in col3.
There are many ways to skin this cat but this should return you all the A2 rows:
select *
from yourTable d
where d.col1 in (select col1
from (select col1
,sum(case when col3 is null then 1 else 0 end) null_values
from yourTable
group by col1
)
where null_values = 0
)
To explain the approach briefly: The inner query counts the number of null col3 values for each col1 value; then the middle query returns the only the distinct col1 values having no associated null col3 values, and the outer query returns the all detail for all rows containing the col1 value.
The above is SQL of course. As you have specified PL/SQL, you could include something like a cursor or the bulk collect into clause as desired to work with the query result set.
As mentioned in my comment below, this is just one way of achieving the output - Oracle analytic functions may also prove helpful. Also depending on the size of your data set, you may want to consider the performance aspect of your chosen method.

SQL Select row depending on values in different columns

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)
);

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;

How to get count values for multiple values in one column

My data is like this
Name Values
A Val1
A Val1
A Val2
A Val2
A Val2
B Val1
B Val2
I want to ouput my data is this way
Name Val1Count Val2Count
A 2 3
B 1 1
I can get the Name and count(*) for Val1 with this query.
select [Name],count(*) FROM [table1]
where [values]='Val1'
group by [Name]
But I am not sure how to get the count(*) for val2 in the same row.
I tried doing this, but looks like this is not supported
select [name],#val1count= (above query for val1), #val2count = (above query for val2)
Please help. Thanks for looking.
This is called pivoting. Some databases provide a PIVOT function. However, you can also do this manually.
SELECT [Name],
SUM ( CASE WHEN [Values]='VAL1' THEN 1 ELSE 0 END ) AS Val1Count,
SUM ( CASE WHEN [Values]='VAL2' THEN 1 ELSE 0 END ) AS Val2Count
FROM [table1]
GROUP BY [Name]
Explanation:
The CASE WHEN ... END gives each row a "boolean" value for whether or not the row matches your condition.
The SUM ( ... ) counts the number of rows which returned "true" (or 1).
The GROUP BY [Name] consolidates the rows down to one row per distinct name.
If you add conditions to a WHERE clause, the CASE WHEN will only see the rows matching your WHERE conditions.

update CTE for multiple columns

I am deriving a CTE using data from 2 tables, and I have a requirement to update 2 columns in this CTE. The I can use UPADTE CTE and then a case statement to update one column, but the second one.
for example
update cte
set col1 = case when thisrecord = thatrecord then 1 else 0 end
col2 = case max(thisrecord) = max(thatrecord) then 1 else 0 end
It gives me error.
If I use
update cte
set col1, set col2
from cte
where this = that
then it says cte is not updatable as it has multiple base tables.
How to solve this puzzle, does anyone has a similar scenario or possible work out?