SQL: How to find the row with a maximum number of a specific value - mysql

I need to find the row containing the most ones in this specific table.
the table looks like that and my output is shown just above the given table.
I am yet unfamiliar with sql so maybe it is easy to solve but I didn't get any solution so far.
Is there a way to say please search for a specific value and sum the found values up and the output should be given in an extra column?

looks pretty basic stuff ... hope this helps :
SELECT X.*,
CASE WHEN X.A=1 THEN 1 ELSE 0 END +
CASE WHEN X.B=1 THEN 1 ELSE 0 END +
CASE WHEN X.C=1 THEN 1 ELSE 0 END +
CASE WHEN X.D=1 THEN 1 ELSE 0 END +
CASE WHEN X.E=1 THEN 1 ELSE 0 END +
CASE WHEN X.F=1 THEN 1 ELSE 0 END AS SUM_ONES
FROM X;

Assuming your column data types are numeric, you can use this:
SELECT
CASE WHEN col1 = 1 THEN '*' ELSE '' END ||
CASE WHEN col2 = 1 THEN '*' ELSE '' END ||
...
AS RowValueSearchString
Then just use a LEN/CHAR_LENGTH function (depending on whatever DB you have) on RowValueSearchString to find the length of the string above. The concatenated string's length will give you the number of occurrences of the value you're looking for within the row.

You can use CASE OR IIF if you are on SQL Server 2012+ as:
CREATE TABLE X (
A INT,
B INT,
C INT,
D INT,
E INT,
F INT
);
INSERT INTO X VALUES
(1, 0, 0, 1, 0, 1),
(2, 0, 1, 2, 1, 0),
(1, 0, 1, 0, 1, 0);
SELECT X.*,
IIF(A = 1, A, 0) +
IIF(B = 1, B, 0) +
IIF(C = 1, C, 0) +
IIF(D = 1, D, 0) +
IIF(E = 1, E, 0) +
IIF(F = 1, F, 0) AS [Σ]
FROM X;
Results:
+---+---+---+---+---+---+---+
| A | B | C | D | E | F | Σ |
+---+---+---+---+---+---+---+
| 1 | 0 | 0 | 1 | 0 | 1 | 3 |
| 2 | 0 | 1 | 2 | 1 | 0 | 2 |
| 1 | 0 | 1 | 0 | 1 | 0 | 3 |
+---+---+---+---+---+---+---+

Related

Multi Auto Increment

I need help, I need to auto increment lines in a select, except that I have to restart my incrementation with each new value of the id .. I already try with (#cnt: = #cnt + 1 ) or COUNT (*) that counts the occurrence, but I never reach my desired result
I get each time
++++++++++++++++++++++++++++++
+ increment | id + value +
++++++++++++++++++++++++++++++
+ 1 | 1 | foo +
+ 2 | 1 | bar +
+ 3 | 2 | foo +
+ 4 | 3 | bar +
+ 5 | 3 | foo +
++++++++++++++++++++++++++++++
While I would like that
++++++++++++++++++++++++++++++
+ increment | id + value +
++++++++++++++++++++++++++++++
+ 1 | 1 | foo +
+ 2 | 1 | bar +
+ 1 | 2 | foo +
+ 1 | 3 | bar +
+ 2 | 3 | foo +
++++++++++++++++++++++++++++++
Here is an approach that leverages an approach documented by https://www.xaprb.com/blog/2006/12/15/advanced-mysql-user-variable-techniques/. It utilizes variable and avoids any Lazy evaluation issues as "MySQL doesn't evaluate expressions containing user variables until they are sent to the client". It use the approach of using a functions to force immediate evaluation of the variables.
Here is what I used on sqlfiddle.com to try out:
Table and creation and insert of values.
CREATE TABLE Table1
(`Id` int, `value` varchar(3))
;
INSERT INTO Table1
(`Id`, `value`)
VALUES
(1, 'foo'),
(1, 'bar'),
(2, 'foo'),
(3, 'bar'),
(3, 'foo')
;
And the sql query for MySQL
set #increment := 0, #id := '';
select #increment, id, value
from Table1
where 0 <= greatest(
#increment := if(#id = id, #increment + 1, 1),
least(0, #id := id));
Here is the result:
#increment id value
1 1 foo
2 1 bar
1 2 foo
1 3 bar
2 3 foo

Print 'O' with odd id and 'E' with even id in sql

I have to write an SQL query for the following:
Input:
Id | Name
-- | ----
1 | A
2 | B
3 | C
Output:
Id | Name | IdType
-- | ---- | -----
1 | A | O
2 | B | E
3 | C | O
I can extract odd or even rows by putting where condition Id % 2 = 0. But I'm not sure how to put 'O' or 'E' in the new column.
Like this, using the IF() function:
SELECT Id, Name, IF(Id % 2 = 0, 'E', 'O') AS IdType FROM table_name;
You make use of CASE and print E when Id%2=0 and O if Id%2 is not equal to 0
SELECT Id,Name,
CASE WHEN (Id%2)=0 THEN 'E'
ELSE 'O' END AS IdType
FROM [YourTable]
Use this query If you want to update your table
UPDATE table_name SET IdType = CASE
WHEN mod (Id, 2) = 0 THEN 'E'
WHEN mod (Id, 2) <> 0 THEN 'O'
ELSE IdType
END
If you just want to print,then Robby Cornelissen had a perfect answer for you

Order the resulting rows based on multiple columns

I have to put down the lines that have two distinct fields with value = 0
Let me explain, all records that have stock_it=0 and stock_eu=0 must go to the bottom of the results
I have used this solution, however, it is not strictly correct because it puts down even rows that do not have both values = 0
$dati = mysql_query("
SELECT *
FROM $tb_article
ORDER BY
FIELD($tb_art.article_status,'n') DESC,
FIELD($tb_art.article_stock_it,'0') ASC,
FIELD($tb_art.article_stock_eu,'0') ASC,
$tb_art.article_rank
");
article_status=n indicates new products and they have to stay on top!
Push to bottom all the article that have stock IT and stock EU = 0 (products not available)
In the end, order the rest of the articles according to the rank assigned
You can use the CASE statement in ORDER BY, like this:
SELECT *
FROM $tb_article
ORDER BY
CASE WHEN article_status = 'n' THEN 0
WHEN article_stock_it = 0 THEN 100000
WHEN article_stock_eu = 0 THEN 100000
ELSE article_rank
END
If you want to use ORDER BY FIELD :
SQL Fiddle
MySQL 5.6 Schema Setup:
CREATE TABLE tb_article
(
article_stock_it int,
article_stock_eu int,
article_status varchar(11),
article_rank int
);
INSERT INTO tb_article VALUES
(1, 1, 'n', 1)
, (0, 1, 'n', 1)
, (0, 0, 'n', 1)
, (1, 1, 'o', 1)
, (1, 1, 'o', 2);
Query 1:
SELECT *
FROM tb_article
ORDER BY
FIELD(tb_article.article_status,'n') DESC,
FIELD(
IF(tb_article.article_stock_it = 0 AND tb_article.article_stock_eu = 0,'1','0')
,'0') DESC,
tb_article.article_rank
Results:
| article_stock_it | article_stock_eu | article_status | article_rank |
|------------------|------------------|----------------|--------------|
| 1 | 1 | n | 1 |
| 0 | 1 | n | 1 |
| 0 | 0 | n | 1 |
| 1 | 1 | o | 1 |
| 1 | 1 | o | 2 |

How to do a cascading decrement across multiple columns

I have N columns: A, B, C, .. N each are decimal(8,2).
I want to write a stored procedure that takes a row id and a single decimal(8,2) X.
I want it to decrement A until A reaches zero OR until it has reduced it by X. If A reaches zero and X was greater that A then I want to decrement B by X - A's original value and so on.
example:
select * from foo_table where id = 0;
| id| A | B | C |..
+---+---+---+---+
| 0 | 5 | 3 | 2 |
call my_stored_proc(0,9);
select * from foo_table where id = 0;
| id| A | B | C |..
+---+---+---+---+
| 0 | 0 | 0 | 1 |
What would be the recommended and performant way of doing this?
Given your sample data this query does the job:
UPDATE t
JOIN (
SELECT
t.id,
GREATEST(A - #a, 0) A,
#a := GREATEST(#a - A, 0),
GREATEST(B - #a, 0) B,
#a := GREATEST(#a - B, 0),
GREATEST(C - #a, 0) C,
#a := GREATEST(#a - C, 0)
FROM
t
, (SELECT #a := 9) var_init_subquery
WHERE id = 0
ORDER BY id
) sq ON t.id = sq.id
SET t.A = sq.A
, t.B = sq.B
, t.C = sq.C;
see it working live in an sqlfiddle
here you can read more about variables in queries

How to handle empty strings like you can nulls with isnull()?

I have small problem parsing strings in SQL Server.
I have a table like this:
emp
sn | code | sal
1 | 1100F- | 100
2 | | 200
3 | 97535-GO | 300
4 | 97530-GO | 300
5 | | 600
6 | 9830 |200
Based on this table data I'd like to output the results like below:
sn | code | Changed | sal
1 | 1100F | NA | 100
2 | 0 | NA | 200
3 | 97535 | GO | 300
4 | 97530 | GO |300
5 | 0 | NA |600
6 |9830 | NA |200
The Changed column should contain everything from the code column after the -, there is nothing after the - or there is no -, I should use NA.
My current code is:
select
sn,
code,
sal case WHEN CHARINDEX('-',code)>0
THEN SUBSTRING(code,CHARINDEX('-',code)+1,len(code))
ELSE 'NA' END changed
from emp
The problem I am having is that for the first row, I am getting an empty string instead of NA, can someone help change it so that if there is a - without a code, it displays NA?
This does what you want, but I'm not entirely happy with it because of the duplication:
select
sn,
case when charindex('-', code) > 0
then
case substring(code, charindex('-', code) + 1, len(code))
when '' then 'NA'
else substring(code, charindex('-', code) + 1, len(code))
end
else 'NA'
end
from emp
But the extra nested case will ensure that empty codes have 'NA'.
It might make more sense to define a scalar value function for this and use some variables instead, like so:
create function GetChanged(#code varchar(10)) returns varchar(10)
as
begin
declare #result varchar(10) = 'NA';
declare #dashIndex int = charindex('-', #code);
if (#dashIndex > 0)
begin
declare #changed varchar(10) = substring(#code, #dashIndex + 1, len(#code))
if (#changed != '')
set #result = #changed;
end;
return #result;
end;
SELECT sn,
CASE WHEN ISNULL((CASE WHEN CHARINDEX('-',code)>0 THEN SUBSTRING(code,1,CHARINDEX('-',code,1)-1) ELSE code END),'')='' THEN '0'
ELSE CASE WHEN CHARINDEX('-',code)>0 THEN SUBSTRING(code,1,CHARINDEX('-',code,1)-1) ELSE code END
END AS Code,
CASE (CASE WHEN CHARINDEX('-',code)>0 THEN SUBSTRING(code,CHARINDEX('-',code,1)+1,LEN(code)) ELSE 'NA' END)
WHEN '' THEN 'NA'
ELSE CASE WHEN CHARINDEX('-',code)>0 THEN SUBSTRING(code,CHARINDEX('-',code,1)+1,LEN(code)) ELSE 'NA' END
END AS changed,
sal
FROM EMP
SQl Fiddle