Mysql display field name where value is specific - mysql

I have a table like this:
+------------------------+-------+------+-------+------+
| user | TELPE | CRS2 | MECAN | GOPI |
+------------------------+-------+------+-------+------+
| user1.foo#my-email.com | NULL | NULL | 1 | NULL |
+------------------------+-------+------+-------+------+
| user2.foo#my-email.com | 1 | NULL | 1 | NULL |
+------------------------+-------+------+-------+------+
I'm struggling to find the request that would returned the columns name for a specific user where the value is 1.
Select manually column is not an option as if there is only 4 columns today,
there'll may be 300 next week.
for instance the search for the user1 would give this this result:
+-------------+
| Books |
+-------------+
| MECAN |
+-------------+
and for user2:
+-------------+
| Books |
+-------------+
| TELPE |
+-------------+
| MECAN |
+-------------+
My Mysql skills are not very high so any help is appreciated,
Many thanks by advance.

You need to convert the columns into rows this process is called unpivot.
You can do that with UNIONS.
Query
SELECT
USER
, TELPE AS 'column_value'
, 'TELPE' AS 'column_source'
FROM
users
WHERE
TELPE = 1
UNION ALL
SELECT
USER
, CRS2 AS 'column_value'
, 'CRS2' AS 'column_source'
FROM
users
WHERE
CRS2 = 1
UNION ALL
SELECT
USER
, MECAN AS 'column_value'
, 'MECAN' AS 'column_source'
FROM
users
WHERE
MECAN = 1
UNION ALL
SELECT
USER
, GOPI AS 'column_value'
, 'GOPI' AS 'column_source'
FROM
users
WHERE
GOPI = 1
Result
user column_value column_source
---------------------- ------------ ---------------
user2.foo#my-email.com 1 TELPE
user1.foo#my-email.com 1 MECAN
user2.foo#my-email.com 1 MECAN
Now we can use this query as a delivered table to filter the results you need.
Query
SELECT
DISTINCT
column_source
FROM (
SELECT
USER
, TELPE AS 'column_value'
, 'TELPE' AS 'column_source'
FROM
users
WHERE
TELPE = 1
UNION ALL
SELECT
USER
, CRS2 AS 'column_value'
, 'CRS2' AS 'column_source'
FROM
users
WHERE
CRS2 = 1
UNION ALL
SELECT
USER
, MECAN AS 'column_value'
, 'MECAN' AS 'column_source'
FROM
users
WHERE
MECAN = 1
UNION ALL
SELECT
USER
, GOPI AS 'column_value'
, 'GOPI' AS 'column_source'
FROM
users
WHERE
GOPI = 1
)
AS
users
WHERE
users.user = 'user1.foo#my-email.com'
AND
users.column_value = 1
Result
| column_source |
|---------------|
| MECAN |
demo http://www.sqlfiddle.com/#!9/3ed091/19
EDITED
Select manually column is not an option as if there is only 4 columns today, there'll may be 300 next week.
Then you need to move to dynamic SQL generating.
First when are going to need a number generator this query will generate 1000 numbers from 2 to 1001.
Why we need a number generator will become more clear later on.
Query
SELECT
#row := #row + 1 AS number
FROM (
SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
)
AS row1
CROSS JOIN (
SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
)
AS row2
CROSS JOIN (
SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
)
AS row3
CROSS JOIN (
SELECT #row := 1
)
AS init_user_param
Result
number
2
3
4
5
6
7
8
9
10
....
....
990
991
992
993
994
995
996
997
998
999
1000
1001
Now we need a way to get all the column fore the table users.
Query
SELECT
GROUP_CONCAT(COLUMN_NAME) AS COLUMN_NAME
FROM
information_schema.COLUMNS
WHERE
TABLE_NAME = 'users'
AND
TABLE_SCHEMA <> 'performance_schema'
Result
COLUMN_NAME
----------------------------
user,TELPE,CRS2,MECAN,GOPI
Now we want to generate a unique list like
user TELPE
user CRS2
...
...
user GOPI
Now we combine the number generator with the query to get the columns.
We also use SUBSTRING_INDEX to spilt the comma separated values.
Query
SELECT
DISTINCT
SUBSTRING_INDEX(SUBSTRING_INDEX(COLUMN_NAME, ',', 1), ',', -1) column1
, SUBSTRING_INDEX(SUBSTRING_INDEX(COLUMN_NAME, ',', generator.number), ',', -1) column2
FROM (
SELECT
GROUP_CONCAT(COLUMN_NAME) AS COLUMN_NAME
FROM
information_schema.COLUMNS
WHERE
TABLE_NAME = 'users'
AND
TABLE_SCHEMA <> 'performance_schema'
)
AS user_column
CROSS JOIN (
SELECT
#row := #row + 1 AS number
FROM (
SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
)
AS row1
CROSS JOIN (
SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
)
AS row2
CROSS JOIN (
SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
)
AS row3
CROSS JOIN (
SELECT #row := 1
)
AS init_user_param
)
AS generator
Result
column1 column2
------- ---------
user TELPE
user CRS2
user MECAN
user GOPI
To make to SQL generation completely dynamic
Query
SET #sql_union = NULL;
SELECT
GROUP_CONCAT(
CONCAT(
"
SELECT
",column1,"
, ",column2," AS 'column_value'
, '",column2,"' AS 'column_source'
FROM
users
WHERE
",column2," = 1
"
)
SEPARATOR 'UNION ALL'
)
FROM (
SELECT
DISTINCT
SUBSTRING_INDEX(SUBSTRING_INDEX(COLUMN_NAME, ',', 1), ',', -1) column1
, SUBSTRING_INDEX(SUBSTRING_INDEX(COLUMN_NAME, ',', generator.number), ',', -1) column2
FROM (
SELECT
GROUP_CONCAT(COLUMN_NAME) AS COLUMN_NAME
FROM
information_schema.COLUMNS
WHERE
TABLE_NAME = 'users'
AND
TABLE_SCHEMA <> 'performance_schema'
)
AS user_columns
CROSS JOIN (
SELECT
#row := #row + 1 AS number
FROM (
SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
)
AS row1
CROSS JOIN (
SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
)
AS row2
CROSS JOIN (
SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
)
AS row3
CROSS JOIN (
SELECT #row := 1
)
AS init_user_param
)
AS generator
)
AS generator_union_sql INTO #sql_union;
SET #sql = CONCAT(
"
SELECT
DISTINCT
column_source
FROM (
"
,#sql_union,
"
)
AS
users
WHERE
users.user = 'user1.foo#my-email.com'
AND
users.column_value = 1
"
);
PREPARE queryUser FROM #sql;
EXECUTE queryUser;
Result
column_source
---------------
MECAN

I suspect you are looking for something like
SELECT user, if(telpe=1,"TELPE","") as rTELPE, if(CRS2=1,"CRS2","") as rCRS2 from myTable

What I understand for your question is:
SELECT 'TELPE' FROM yourTable WHERE telpe = 1 AND user = 'user1.foo#my-email.com'
UNION ALL
SELECT 'CRS2 ' FROM yourTable WHERE crs2 = 1 AND user = 'user1.foo#my-email.com'
UNION ALL
SELECT 'MECAN' FROM yourTable WHERE mecam = 1 AND user = 'user1.foo#my-email.com'
UNION ALL
SELECT 'GOPI' FROM yourTable WHERE gopi = 1 AND user = 'user1.foo#my-email.com'

Related

Splitting string with '+' seperator into seperate rows and apply aggregation

The data is not static and group of characters separted by + can vary. I want all the characters separated by + to be in row wise and then apply aggregation on the top of it. I am using mysql 5.7.14 in windows.
suppose data is:
group val
a+b 10
a 5
b 6
b+d+c 12
d 13
c+d 12
the output should be like:
grp_item val
a 15
b 28
c 24
d 24
Like i said the MySQL query is complex..
The general idea is a MySQL number generator which generates 1 to 10000 so it supports 10000 separated values with the + sign in the group column.
And it does not matter what data is between the + signs.
Query
SELECT
Table1_unique_groups.`group`
, SUM(Table1.val)
FROM (
SELECT
DISTINCT
SUBSTRING_INDEX(SUBSTRING_INDEX(Table1.`group`, '+', number_generator.number), '+', -1) AS `group`
FROM (
SELECT
#row := #row + 1 AS number
FROM (
SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
) record_1
CROSS JOIN (
SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
) record_2
CROSS JOIN (
SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
) record_4
CROSS JOIN (
SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
) record_5
CROSS JOIN (
SELECT #row := 0
) AS init_user_params
) AS number_generator
CROSS JOIN
Table1
) AS Table1_unique_groups
INNER JOIN
Table1
ON
FIND_IN_SET(Table1_unique_groups.`group`, REPLACE(Table1.group, '+', ','))
GROUP BY
Table1_unique_groups.`group`
Result
| group | SUM(Table1.val) |
| ----- | --------------- |
| a | 15 |
| b | 28 |
| c | 24 |
| d | 37 |
DB Fiddle demo

MYSQL: Find missing values in a sequence by different groups

Hy, little help please, I have a full sequence of 12 items, I identify these items by 2 different groups (12345 and 54321). Now, I need to identify the first sequence of the item "12345" stop at 4 and restart at 10. Something like that:
I have this table:
------------------
|seq |partNumber|
------------------
| 1 | 12345 |
| 2 | 12345 |
| 3 | 12345 |
| 4 | 12345 |
| 10 | 12345 |
| 11 | 12345 |
| 12 | 12345 |
| 5 | 54321 |
| 6 | 54321 |
| 7 | 54321 |
| 8 | 54321 |
| 9 | 54321 |
------------------
I need to find this result:
------------
|Start|Stop|
------------
| 5 | 9 | (partnumber:12345)
------------
the query that I used:
select start, stop from (
select m.partNumber + 1 as start,
(select min(partNumber) - 1 from seq as x where x.partNumber > m.partNumber) as stop
from seq as m
left outer join seq as r on m.partNumber = r.partNumber - 1 where r.partNumber is null) as x
where stop is not null;
But, this query gives me this result:
------------
|Start|Stop|
------------
| 9 | 9 | (partnumber:12345)
------------
Final result:
I want to identify sequence of "12345" starts in 1 ends in 4 (break) restart at 10 ends 12, I have a gap in 5 to 9. The other sequence of "54321" starts at 5 ends in 9, here I don't have a gap.
This is a good application for the structured part of structured query language.
I guess you will never have a value of seq less than zero or greater than the arbitary value 15624. That guess is important: we need a table of all the cardinal numbers in that range to get missing-number detection to work.
Here is such a table
SELECT A.N + 5*(B.N + 5*(C.N + 5*(D.N + 5*(E.N + 5*(F.N))))) AS seq
FROM (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS A
JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS B
JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS C
JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS D
JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS E
JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS F
(If you're using MariaDB, you can use the Sequence table seq_0_to_15624 in place of this lump of SQL code.)
Next, you need a way to find out the lowest and highest value of seq for each part number. You do that like so.
SELECT partNumber, MIN(seq) minSeq, MAX(seq) maxSeq
FROM seq
GROUP BY partNumber
Next, you need to generate a table showing all the possible sequence numbers from minimum to maximum for each part number:
SELECT cardinals.seq, r.partNumber
FROM (
SELECT A.N + 5*(B.N + 5*(C.N + 5*(D.N + 5*(E.N + 5*(F.N))))) AS seq
FROM (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS A
JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS B
JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS C
JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS D
JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS E
JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS F
) cardinals
JOIN (
SELECT partNumber, MIN(seq) minSeq, MAX(seq) maxSeq
FROM seq
GROUP BY partNumber
) r ON cardinals.seq >= r.minSeq AND cardinals.seq <= r.maxSeq
Finally, you can LEFT JOIN that to your original table and do WHERE val IS NULL to locate your missing sequence numbers.
SELECT cardinals.seq, r.partNumber
FROM (
SELECT A.N + 5*(B.N + 5*(C.N + 5*(D.N + 5*(E.N + 5*(F.N))))) AS seq
FROM (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS A
JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS B
JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS C
JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS D
JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS E
JOIN (SELECT 0 AS N UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) AS F
) cardinals
JOIN (
SELECT partNumber, MIN(seq) minSeq, MAX(seq) maxSeq
FROM seq
GROUP BY partNumber
) r ON cardinals.seq >= r.minSeq AND cardinals.seq <= r.maxSeq
LEFT JOIN seq ON cardinals.seq = seq.seq AND r.PartNumber = seq.partNumber
WHERE seq.seq IS NULL

How to find irregular increasements on mySQL

My Table:
id value
1 25
2 96
5 47
6 41
9 78
10 23
How to find irregular increasements(or not existence rows) like following:
Result: 3, 4, 7, 8
I dont want to read each one because of having 50k rows. What do you suggest I do?
Simple approach
Ingredients:
Generator table
outer join
SQL Fiddle
MySQL 5.6 Schema Setup:
create table t ( id int, value int );
insert into t values ( 1, 12 );
insert into t values ( 3, 12 );
insert into t values ( 7, 12 );
insert into t values ( 9, 12 );
Query 1:
select generator.row
from t right outer join
(
SELECT #row := #row + 1 as row FROM
(select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t,
(select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t2,
(select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t3,
(select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t4,
(SELECT #row:=0) t5
) generator
on generator.row = t.id
where t.id is null and generator.row < ( select max( t.id) from t )
Results:
| row |
|-----|
| 2 |
| 4 |
| 5 |
| 6 |
| 8 |
Complex approach
If you need your gap limits, do you need some ingredients:
MySQL Variables
Generator table with at least your max id
Here your query
MySQL 5.6 Schema Setup:
create table t ( id int, value int );
insert into t values ( 1, 12 );
insert into t values ( 3, 12 );
insert into t values ( 7, 12 );
insert into t values ( 9, 12 );
The query:
select generator.row, rFrom, rTo
from (
SELECT #r := #r + 1 as r,
case
when #r < t.id then #r
else Null
end as rFrom,
case
when #r < t.id then t.id - 1
else Null
end as rTo,
#r := t.id
FROM t , (SELECT #r:=0) r
) gaps inner join
(
SELECT #row := #row + 1 as row FROM
(select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t,
(select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t2,
(select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t3,
(select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t4,
(SELECT #row:=0) t5
) generator
on generator.row between gaps.rFrom and gaps.rTo
where rFrom is not null
Results:
| row | rFrom | rTo |
|-----|-------|-----|
| 2 | 2 | 2 |
| 4 | 4 | 6 |
| 5 | 4 | 6 |
| 6 | 4 | 6 |
| 8 | 8 | 8 |
First subquery looks for gaps intervals, second one is a generator to generate missing ids. Be free to execute both queries one by one to understand it.

Select a row for each 'quantity'

Table:
Article | Quantity | pricePerUnit | order_id | article_id
--------|----------|--------------------------------------
14 | 2 | 10.0 | 1 | 1
X1 | 1 | 5.0 | 1 | 2
Expected output:
Article | Quantity | pricePerUnit | order_id
--------|----------|------------------------
14 | 1 | 10.0 | 1
14 | 1 | 10.0 | 1
X1 | 1 | 5.0 | 1
What is a fast SELECT to populate the resultset with 1 row for each quantity per article?
Sorry I didn't try anything, I'm not sure wether this is possible at all. Self join.. would not be a help, grouping functions,..
Maybe GROUP BY order_id, article_id, quantity somehow..
UPDATE: For the max quantity of three just do
SELECT Article, 1 Quantity, pricePerUnit, order_id
FROM articles a JOIN
(
SELECT 1 AS n UNION ALL
SELECT 2 UNION ALL
SELECT 3
) n
ON n.n <= a.Quantity
ORDER BY order_id, Article
Here is SQLFiddle demo
Original answer: You can try
SELECT Article, 1 Quantity, pricePerUnit, order_id
FROM articles a JOIN
(
SELECT a.N + b.N * 10 + 1 n
FROM
(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
) n
ON n.n <= a.Quantity
ORDER BY order_id, Article
An inner select returns 100 rows meaning you can unpivot quantities up to the value of 100. If you need more update it accordingly.
Here is SQLFiddle demo
Given that it is for a report and you have necessary right to create a new table it's best to substitute an inner select with a tally (numbers) table which you can create in the same manner:
CREATE TABLE tally (n int not null auto_increment primary key);
INSERT INTO tally
SELECT a.N + b.N * 10 + 1 n
FROM
(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
ORDER BY n;
And then your query will look like
SELECT Article, 1 Quantity, pricePerUnit, order_id
FROM articles a JOIN tally n
ON n.n <= a.Quantity
ORDER BY order_id, Article
Here is SQLFiddle demo

Get value even if it doesn't exist in table from SQL SELECT statement

I have a MySQL table that looks something like this:
|---ID---|---COUNTER---|
| 1 | 2 |
| 2 | 6 |
| 3 | 1 |
| 5 | 9 |
| 6 | 10 |
I'm looking for a SELECT statement that returns ID's and their COUNTER. The table only have ID's such as: 1,2,3,5,6. Is there a statement where you say: I want ID's 1 to 10 even if they doesn't exist in the table, and if the ID doesn't exist, return the ID anyway with the COUNTER value 0. For example:
|---ID---|---COUNTER---|
| 1 | 2 |
| 2 | 6 |
| 3 | 1 |
| 4 | 0 |
| 5 | 9 |
| 6 | 10 |
| 7 | 0 |
| 8 | 0 |
| 9 | 0 |
| 10 | 0 |
Do I have to create a SELECT statement that contains NOT EXIST parameters?
Thanks in advance, Steve-O
Without creating a temp table:
select t.num as id, coalesce(yt.counter, 0)
from your_table yt
right join (
select 1 as num union select 2 union select 3 union select 4 union select 5 union
select 6 union select 7 union select 8 union select 9 union select 10
) t on yt.id = t.num
order by t.num
and bit more general:
select t.num as id, coalesce(yt.counter, 0)
from your_table yt
right join (
select t1.num + t2.num * 10 + t3.num * 100 as num
from (
select 1 as num union select 2 union select 3 union select 4 union select 5 union
select 6 union select 7 union select 8 union select 9 union select 0
) t1
cross join (
select 1 as num union select 2 union select 3 union select 4 union select 5 union
select 6 union select 7 union select 8 union select 9 union select 0
) t2
cross join (
select 1 as num union select 2 union select 3 union select 4 union select 5 union
select 6 union select 7 union select 8 union select 9 union select 0
) t3
) t on yt.id = t.num
where t.num between (select min(id) from your_table) and (select max(id) from your_table)
You can define limit by yourself here I've used min and max of id value from your_table.
It's not very robust, but if you created a temporary table with the ID's you wanted in it, you could then left join to your table containing ID and Counter which would include all the values:
Declare #tempidtable as table ( imaginaryid int )
insert into #tempidtable ( imaginaryid ) values ( 1 )
insert into #tempidtable ( imaginaryid ) values ( 2 )
insert into #tempidtable ( imaginaryid ) values ( 3 )
select
#temptable.imaginaryid,
ISNULL(yourothertable.counter, 0)
from #tempidtable
left join yourothertable
on #tempidtable.imaginaryid = yourothertable.id
As Tomek says you could loop over the inserts to make it easier to maintain, or possible store the ids you want as a base in another table, using this as the basis for the join rather than a temp table.
Create a table with all possible ID's:
create table Numbers (nr int primary key);
declare i int default 1;
while i < 100000 do
insert into Numbers (nr) values (i);
set i = i + 1;
end while;
Then you can use left join to return all numbers:
select n.NR
, c.Counter
from Numbers n
left join
Counters c
on c.ID = n.NR
You can use left join to solve your issue. Read more about left join here
I think you will have to create (generate in loop) temporary table with the complete sequence of numbers from 1 to N (where N is the MAX(Id) of counted table). Then do left join to that table and apply GROUP BY clause.
You need the range of integers to do an outer join with your table based on ID. Generating a range of integers is dependent on the SQL vendor if you do not want to use a temporary table. See SQL SELECT to get the first N positive integers for hints on how to do this based on your SQL vendor.