Count each column if the value is met for a row - sql

I've been searching far and wide (pun intended) but haven't found a solution yet.
So I got a table with 19 columns.
pokemon name
against_bug
against_dark
against_dragon
against_electric
against_fairy
against_fight
against_fire
against_flying
against_ghost
against_grass
against_ground
against_ice
against_normal
against_poison
against_psychic
against_rock
against_steel
against_water
Each of the "against_xxx" columns can have a value of 0,5, 1, 2 or 4.
I want each row to count how many of these columns have a value of 2 or higher in order to determine which pokemon has the most vulnerabilities.
I have no idea how to approach this.

Please look at Stu's suggestion in the comments on your question. Normalizing your table would be a great help.
Now you need to do something like this:
SELECT
pokemon,
CASE WHEN against_bug >= 2 THEN 1 ELSE 0 END +
CASE WHEN against_dark >= 2 THEN 1 ELSE 0 END +
CASE WHEN against_dragon >= 2 THEN 1 ELSE 0 END +
CASE WHEN against_electric >= 2 THEN 1 ELSE 0 END +
--[....repeat this for all your columns....]
FROM your_table
A normalized table would look like this:
pokemon
against_type
against_value
Pickachu
against_bug
1
Pickachu
against_dark
2
Pickachu
against_dragon
0.5
Pickachu
against_electric
1
Pickachu
(etc)
(etc)
Blastoid
against_bug
1
Blastoid
against_dark
2
Blastoid
against_dragon
2
Blastoid
against_electric
4
Blastoid
(etc)
(etc)
In this case you could write a much simpler query:
SELECT
pokemon,
count(*) AS number_of_vulnerabilities
FROM your_table
WHERE against_value >= 2
GROUP BY pokemon

Related

Give first duplicate a 1 and the rest 0

I have data which contains 1000+ lines and in this it contains errors people make. I have added a extra column and would like to find all duplicate Rev Names and give the first one a 1 and all remaining duplicates a 0. When there is no duplicate, it should be a 1. The outcome should look like this:
RevName ErrorCount Duplicate
Rev5588 23 1
Rev5588 67 0
Rev5588 7 0
Rev5588 45 0
Rev7895 6 1
Rev9065 4 1
Rev5588 1 1
I have tried CASE WHEN but its not giving the first one a 1, its giving them all zero's.
Thanks guys, I am pulling out my hair here trying to get this done.
You could use a case expression over the row_number window function:
SELECT RevName,
Duplicate,
CASE ROW_NUMER() OVER (PARTITION BY RevName
ORDER BY (SELECT 1)) WHEN 1 THEN 1 ELSE 0 END AS Duplicate
FROM mytable
SQL tables represent unordered sets. There is no "first" of anything, unless a column specifies the ordering.
Your logic suggests lag():
select t.*,
(case when lag(revname) over (order by ??) = revname then 0
else 1
end) as is_duplicate
from t;
The ?? is for the column that specifies the ordering.

Dynamically setting Where condition in query

I am looking for a method where I need to have conditions on my WHERE clause change dynamically based on the data.
Please find the mock data for my scenario.
-----------------------------------
ConditionID ConditionName
-----------------------------------
1 N/A
2 Over
3 Under
--------------------------------------------------------------
ID Amount ThresholdAmount ConditionID
--------------------------------------------------------------
1 90 100 3
2 190 100 2
3 90 100 2
4 190 100 3
5 90 100 1
I need to compare the [Amount] against the [ThresholdAmount] based on the [ConditionID]. For example if the condition is 'Over' then the [Amount] should be over the [ThresholdAmount] and if not satisfied then the record should be filtered out.
NOTE: I am just looking if there is any better approach than mine.
My Approach:
WHERE
1 = CASE
WHEN ConditionName = 'OVER' THEN
CASE WHEN ([Amount] >= [ThresholdAmount]) THEN 1 ELSE 0 END
WHEN ConditionName = 'UNDER' THEN
CASE WHEN ([Amount] <= [ThresholdAmount]) THEN 1 ELSE 0 END
WHEN ConditionName = 'N/A' THEN
1
END
Thanks,
Prakazz
I think you are using the word "Dynamically" wrong here, what you mean is not really dynamic. Search for dynamic sql to get a feel for the difference.
It's usually best to avoid case expressions in the where clause. Your where clause can be rewritten as:
WHERE (ConditionName = 'OVER' AND [Amount] >= [ThresholdAmount])
OR (ConditionName = 'UNDER' AND [Amount] <= [ThresholdAmount])
OR ConditionName = 'N/A'
By the way, you mention "if the condition is 'Over' then the [Amount] should be over the [ThresholdAmount]", but in your code you check whether Amount is 'over' or equal to ThresholdAmount. I followed what your code does.
I also extended your assumption that the database is case-insensitive.

Counting how many data that exist [SQL]

im not sure about this question is already asked by anyone else or not yet because this is actually easy but my head is just still can't see the way out of this problem.
this is just like how many times that we do sampling at the material.
SELECT
TABLE01.MATERIAL_NO,
TABLE01.Sample_Tempt1,
TABLE01.Sample_Tempt2,
TABLE01.Sample_Tempt3,
TABLE01.Sample_Tempt4,
TABLE01.Sample_Tempt5
FROM
TABLE01
is it possible to create another column to show count of sample_tempt times?
i mean, if the tempt1 tempt2 data are exist, the column shows 2, when tempt2, tempt4 and tempt5 data are exist, the column show 3. and so on.
Thank you for helping me ^^
Sample :
Material no | Sample_Tempt1 | Sample_Tempt2 | Sample_Tempt3 | Sample_Tempt4 | Sample_Tempt5 |
PO1025 120 150 102
PO1026 122
For the PO1025, i want to create new column that generate "3" because the sample data that exist is only 3, for the PO1026 i want it generate "1" since the sample data that exist is only "1". quite simple right?
If "by exist" you mean "value is not NULL", then you can count the number of non-NULL values in each row as:
SELECT t1.MATERIAL_NO,
t1.Sample_Tempt1, t1.Sample_Tempt2, t1.Sample_Tempt3, t1.Sample_Tempt4, t1.Sample_Tempt5,
((case when t1.sample_temp1 is not null then 1 else 0 end) +
(case when t1.sample_temp2 is not null then 1 else 0 end) +
(case when t1.sample_temp3 is not null then 1 else 0 end) +
(case when t1.sample_temp4 is not null then 1 else 0 end) +
(case when t1.sample_temp5 is not null then 1 else 0 end)
) as NumTempts
FROM TABLE01 t1;
Note that I introduced a table alias. This makes the query easier to write and to read.

SQL server use case in order by

One of the column in my table like this:
Symbol
586fast
urgent
243late
296fast
122late
155fast
I need urgent in first then records with fast then records with late like this:
urgent
586fast
296fast
155fast
243late
122late
I am getting urgent in first row by:
ORDER BY CASE WHEN substring(Symbol, len(Symbol) - 2, 3) = 'ent'THEN 0 ELSE 1 END
After that it is order by number in records.
Since you said you are on 2005 you could do something like this.
order by case
when Symbol = 'urgent' then 1
when Symbol like '%fast' then 2
when Symbol like '%late' then 3
else 4
end
ORDER BY CASE WHEN CHARINDEX('urgent', Symbol) > 0 THEN 1
WHEN CHARINDEX('fast', Symbol) > 0 THEN 2
WHEN CHARINDEX('late', Symbol) > 0 THEN 3
ELSE 4
END

Reorder integer except for value 0 with sql

I'm trying to get an ordered list of rows out of my MYSQL database table based upon an integer value 'place'.
SELECT * FROM mytable
ORDER BY place;
This works okay, except that all rows with value place=0 should appear at the end of the table.
So if my table is:
name place
---- -----
John 1
Do 2
Eric 0
Pete 2
it should become:
name place
---- -----
John 1
Do 2
Pete 2
Eric 0
order by case when place = 0 then 1 else 0 end asc, place asc
that way you get all the non-zeroes ordered first.
SELECT *
FROM myTable
ORDER BY place>0 DESC, place
is a solution without CASE
SELECT *
FROM myTable
ORDER BY CASE place WHEN 0 THEN 9999 ELSE place END
This approach implies that we known that 9999 (or some other value) is bigger than all possible values in the place column.
Alternatively we can sort by two values as in:
ORDER BY CASE place WHEN 0 THEN 0 ELSE -1 END, place