Trying to create a flag based on ranking values in two separate columns - sql

I have a query where I have duplicate rows for certain ID's, but have two different columns created by window functions and need to create a flag for each row based on a certain order. I've provided an example below of what the data looks like.
I have a RANK_ONE column that returns a ranked value or null and not every ID has a value, but if it has a one, I need it to return a 1 for the row that contains 1.
The RANK_TWO column is basically the same, but I need to flag the 1 row IF there isn't already a 1 flagged from RANK_ONE for the same ID.
The PRIMARY column is my desired outcome. Any thoughts?
I don't know if I've just been in the query too long and can't see a simple solution right in front of me, but it's driving me nuts trying to figure it out.

You seem to want rank_one if it is every 1 for the id and otherwise rank_two:
select t.*,
(case when max(case when rank_one = 1 then 1 else 0 end) over (partition by id) = 1 and rank_one = 1 then 1
when max(case when rank_one = 1 then 1 else 0 end) over (partition by id) = 1 then 0
when rank_two = 1 then 1
else 0
end) as primary
from t;

Related

Count the occurrences of a given list of values in a column using a single SQL query

I would like to get the count of occurrences of a given list of values in a column using a single SQL query. The operations must be optimised for performance.
Please refer the example given below,
Sample Table name - history
code_list
5lysgj
627czl
1lqnd8
627czl
dtrtvp
627czl
esdop9
esdop9
3by104
1lqnd8
Expected Output
Need to get the count of occurrences for these given list of codes 627czl, 1lqnd8, esdop9, aol4m6 in the format given below.
code
count
627czl
3
esdop9
2
1lqnd8
2
aol4m6
0
Method I tried in show below but the count of each input is shown as a new column using this query,
SELECT
sum(case when h.code_list = 'esdop9' then 1 else 0 end) AS count_esdop9,
sum(case when h.code_list = '627czl' then 1 else 0 end) AS count_627czl,
sum(case when h.code_list = '1lqnd8' then 1 else 0 end) AS count_1lqnd8,
sum(case when h.code_list = 'aol4m6' then 1 else 0 end) AS count_aol4m6
FROM history h;
Note - The number inputs need to be given in the query in 10 also the real table has millions of records.
If i properly understand you need to get the count of occurrences for the following codes: 627czl, 1lqnd8, esdop9.
In this case you can try this one:
SELECT code_list, count(*) as count_
FROM history
WHERE code_list in ('627czl','1lqnd8','esdop9')
GROUP BY code_list
ORDER BY count_ DESC;
dbfiddle
If you need to get the count of occurrences for all codes you can run the following query:
SELECT code_list, count(*) as count_
FROM history
GROUP BY code_list
ORDER BY count_ DESC;
you can try to use GROUP BY
Something like this
SELECT code_list, COUNT(1) as 'total' ROM h GROUP by code_list order by 'total' ;

SQL or operator how to use with having

i have a table which i am joining with with operator. I can have 2 combinations id that table FDEL - 1 or 0 and FDVE 1 or 0, what i would like to do is to dispay if - item has fdve, or item has fdel (and count) but it doesnt work (i can see all fdve, or all fdel)
select
lpad(purchase_id,10,0) as purchase_id,
sum(has_label_fdel) as FDEL_count,
case when LABELS like '%FDVE%' then 1 else 0 end as HAS_LABEL_FDVE,
sum(has_label_fdve) as FDVE_count
from
"SRC_ORACLEIWP"."PURCHASE_ANALYSIS_RULES"
group by
lpad(purchase_id,10,0),has_label_fdve
having FDVE_count>0 -- FDEL_count>0
You want one resut row per product, so group by product only. Use SUMfor counting and MAX for the aggregated yes/no.
select
lpad(purchase_id,10,0) as padded_purchase_id,
max(has_label_fdve) as has_labels_fdve,
sum(has_label_fdve) as fdve_count,
max(has_label_fdel) as has_labels_fdel,
sum(has_label_fdel) as fdel_count
from src_oracleiwp.purchase_analysis_rules
group by padded_purchase_id
having has_labels_fdve = 1
or has_labels_fdel = 1
order by padded_purchase_id;
I've changed your alias names slightly, so they are digfferent from the columns you have (because such ambiguities can sometimes lead to problems).
The check on labels like '%FDVE%' is unnecessary, because you already have the has_label_fdve flag, which is always 0 or 1. Or so it seems. If the flags can be null, use COALESCE on them or do use LIKE expressions.
If you don't have has_label_fdve and has_label_fdel yet, use the labels column instead:
select
lpad(purchase_id,10,0) as padded_purchase_id,
max(case when labels like '%FDVE%' then 1 else 0 end) as has_labels_fdve,
sum(case when labels like '%FDVE%' then 1 else 0 end) as fdve_count,
max(case when labels like '%FDEL%' then 1 else 0 end) as has_labels_fdel,
sum(case when labels like '%FDEL%' then 1 else 0 end) as fdel_count
from src_oracleiwp.purchase_analysis_rules
group by padded_purchase_id
having has_labels_fdve = 1
or has_labels_fdel = 1
order by padded_purchase_id;

Mark values with diffreent tag in sql

I have one endpoint that is 7. I would like to few numbers 40,35,30,26,22,18,12 mark as completed.(This is an example. The value may be different) and few numbers 13,17,21,27,32,38,43 mark as pending. (This is an example. The value may be different) Can we achieve by SQL statement? for number details, please find the image.
If your DBMS supports Windowed Aggregates:
with cte as
( select ID, point,
-- find all rows after the latest 7 row
sum(case when point = 7 then 1 end)
over (order by ID DESC) as cumsum
from tab
)
select ID, point,
case when point = 7 then 'endpoint'
when cumsum is null then 'pending' -- no 7 after those IDs
else 'completed'
end
from cte
If you want everything before the first "7" as "completed" and the rest as "pending", then you can use window functions and cumulative logic. One method is:
select t.*,
(case when point = 7 then null
when id < min(case when point = 7 then id end) over ()
then 'complete'
else 'pending'
end) as mark
from t ;

GROUP BY with COUNT condition

I have a result set such as:
Code No
1 *
1 -
1 4
1
1
Now i basically want a query that has 2 columns, a count for the total amount and a count for those that dont have numbers.
Code No_Number Total
1 4 5
Im assuming this needs a group by and a count but how can i do the 2 different counts in a query like this?
This is what i had so far, but i am a bit stuck with the rest of it
SELECT CODE,NO
Sum(Case when No IN ('*', '-', '') then 1 else 0 end) as Count
I think you basically just need GROUP BY:
SELECT CODE,
SUM(Case when No IN ('*', '-', '') then 1 else 0 end) as Count,
COUNT(*) as total
FROM t
GROUP BY CODE;
Well, this took a moment :-), however here it is...I have used a CASE statement to create and populate the No_Number column; the database gives the row in the original table a value of 1 if the original table value is a number or gives it a NULL and discards it from the COUNT if not. Then when it makes the count it is only recognising values which were originally numbers and ignoring everything else..
If the result set is in a table or temp table:
SELECT Code,
COUNT(CASE WHEN [No] NOT LIKE '[0-9]' THEN 1 ELSE NULL END) AS No_Number,
COUNT(Code) AS Total
FROM <tablename>
GROUP BY Code
If the result set is the product of a previous query you can use a CTE (Common Table Expression) to arrive at the required result or you could include parts of this code in the earlier query.

Impala SQL, return value if a string exists within a subset of values

I have a table where the id field (not a primary key) contains either 1 or null. Over the past several years, any given part could have been entered multiple times with one, or both of these possible options.
I'm trying to write a statement that will return some value if there is ever a 1 associated with the select statement. There are lots of semi-duplicate rows, some with 1 and some with null, but if there is ever a 1, I want to return true, and if there are only null values, I want to return false. I'm not sure how to code this though.
If this is my SELECT part,id from table where part = "ABC1234" statement
part id
ABC1234 1
ABC1234 null
ABC1234 null
ABC1234 null
ABC1234 1
I want to write a statement that returns true, because 1 exists in at least one of these rows.
The closest I've come to this is by using a CASE statement, but I'm not quite there yet:
SELECT
a1.part part,
CASE WHEN a2.id is not null
THEN
'true'
ELSE
'false'
END AS id
from table.parts a1, table.ids a2 where a1.part = "ABC1234" and a1.key = a2.key;
I also tried the following case:
CASE WHEN exists
(SELECT id from table.ids where id = 1)
THEN
but I got the error subqueries are not supported in the select list
For the above SELECT statement, how do I return 1 single line that reads:
part id
ABC1234 true
You can use conditional aggregation to check if a part has atleast one row with id=1.
SELECT part,'True' id
from parts
group by part
having count(case when id = 1 then 1 end) >= 1
To return false when the id's are all nulls use
select part, case when id_true>=1 then 'True'
when id_false>=1 and id_true=0 then 'False' end id
from (
SELECT part,
count(case when id = 1 then 1 end) id_true,
count(case when id is null then 1 end) id_false,
from parts
group by part) t