Sum Of column against id.in (1:6:3) this format - mysql

my Ui return id in this format 1:6:3 so i want to sum the value corresponding to that id. example if id return is = 1:6:3
then output will= 100+50+140=290

How about SELECT SUM(value) FROM table WHERE ID IN (1,6,3) ?

Took some time to figure out what's the question. I think I got it now - it is about Apex and its "capability" to allow multiple selection from, for example, a select list or shuttle item. When you do that, those multiple values are represented as a colon-separated string.
If we suppose that it was a select list item, it requires two values: display and return. The resulting string contains those return values, which means that you selected several items whose return values were 1, 6 and 3 and - as described above - stored as 1:6:3.
In order to do something with them - in your example, sum values from the table - you'll have to first parse that string into rows and join the result with the "real" table (the one whose image you posted). Let's call it the TEST table; here it is:
SQL> create table test (id number, value number, name varchar2(2));
Table created.
SQL> insert into test
2 select 1, 100, 'a' from dual union
3 select 2, 110, 'b' from dual union
4 select 3, 140, 'c' from dual union
5 select 4, 203, 'd' from dual union
6 select 5, 230, 'e' from dual union
7 select 6, 50 , 'f' from dual;
6 rows created.
In Apex, you'd do it as follows: P1_ITEM is a Page 1 item that contains the '1:6:3' string:
select sum(t.value) result
from test t join (select regexp_substr(:P1_ITEM, '[^:]+', 1, level) id
from dual
connect by level <= regexp_count(:P1_ITEM, ':') + 1
) a on a.id = t.id;
Just to demonstrate it in SQL*Plus, this is the result:
SQL> select sum(t.value) result
2 from test t join (select regexp_substr('&&P1_ITEM', '[^:]+', 1, level) id
3 from dual
4 connect by level <= regexp_count('&&P1_ITEM', ':') + 1
5 ) a on a.id = t.id;
Enter value for p1_item: 1:6:3
RESULT
----------
290
SQL>

Related

Selecting row value only if other rows are equal

I have a table with an id column and a source column.
I want to return only the source values that all ids share.
E.g. in the table below id 1,2,3 all share 10 and 20, but id 3 is missing the source value 30, so 30 is not valid and I want to return 10 and 20.
I'm using MySQL and want to put this in a stored procedure.
How do I do this?
id
source
1
10
1
20
1
30
2
10
2
20
2
30
3
10
3
20
You may use COUNT(DISTINCT) function as the following:
SELECT source FROM
table_name
GROUP BY source
HAVING COUNT(DISTINCT id)=(SELECT COUNT(DISTINCT id) FROM table_name)
To do this within a stored procedure:
CREATE PROCEDURE getSourceWithAllIds()
BEGIN
SELECT source FROM
table_name
GROUP BY source
HAVING COUNT(DISTINCT id)=(SELECT COUNT(DISTINCT id) FROM table_name);
END
The idea is to select the count of distinct id values for each source, which is done by COUNT(DISTINCT id)... GROUP BY source, then match this count with the distinct count of all id values existed in the table; HAVING COUNT(DISTINCT id)=(SELECT COUNT(DISTINCT id) FROM table_name).
If the two counts are equal, then the source have all the distinct ids existed in the table.
i.e. All distinct ids in the table are (1, 2, 3) count = 3, and distinct ids for a source =10 are (1, 2, 3) count=3. For source = 30, the distinct ids are (1, 2) count=2 so it will not be returned by the query (2<>3).
See a demo.

How to count the number of entries in the list when requesting Select?

I apologize for the possible incorrectness in the presentation, I use a translator. Let's say there is a users table in which there is an id field. And there is a list that lists the id numbers and some of them are repeated. My query
select id, count(*)
from users
where id in (3, 10, 10, 10)
group by id;
returns the following 3 - 1, 10 - 1. And I would like to get 3 - 1, 10 - 3, and so on. Is it possible to get it somehow?
UPD.
The data in the list (3, 10, 10, 10) is just an example, the exact number of digits is not known because they are returned from another question.
You would need to use a join. You can put the values in a derived table for this:
select id, count(*)
from users u join
(select 3 as id union all
select 10 as id union all
select 10 as id union all
select 10 as id union all
) i
using(id)
group by id;

How to return records in MySQL with "custom" ordering

I'm trying to return records based on their IDs in MySQL without ordering.
But when I run the query it will order them from the lowest ID number to highest one.
SELECT * FROM events WHERE id=11 or id=4 or id=9 or id=5
The result will like these: 4,5,9,11
How can return like this : 11,4,9,5
Try using ORDER BY FIELD (id, ...):
SELECT *
FROM events
WHERE id IN (4, 5, 9, 11)
ORDER BY FIELD (id, 11, 4, 9, 5)
Demo
As to why your current query is showing the 4,5,9,11 order, even without your using an explicit ORDER BY clause, one explanation is that the id column is the clustered primary key for your table. In that case, the data would actually be stored in this order on disk, and when selecting, this would be the natural order returned.
Edit:
On other database vendors, which don't support FIELD, we can order using a CASE expression:
SELECT *
FROM events
WHERE id IN (4, 5, 9, 11)
ORDER BY
CASE WHEN id = 11 THEN 1
WHEN id = 4 THEN 2
WHEN id = 9 THEN 3
WHEN id = 5 THEN 4
ELSE 5 END;
I believe you want to use FIELD()
SELECT * FROM events WHERE id=11 or id=4 or id=9 or id=5
ORDER BY FIELD(id, 11,4,8,5)
Or the more ANSI SQL method (works also for other databases vendors)
SELECT
events.*
FROM (
SELECT
11 AS id
, 1 AS position
UNION ALL
SELECT
4 AS id
, 2 AS position
UNION ALL
SELECT
8 AS id
, 3 AS position
UNION ALL
SELECT
5 AS id
, 4 AS position
) AS sorting
INNER JOIN
events
ON
sorting.id = events.id
ORDER BY
sorting.position ASC
Or the better ANSI SQL like it should (works also for other databases vendors)
SELECT * FROM events WHERE id=11 or id=4 or id=9 or id=5
ORDER BY CASE WHEN id = 11 THEN 1
WHEN id = 4 THEN 2
WHEN id = 8 THEN 3
WHEN id = 5 THEN 4
ELSE 5
END
** Updateded
As you want fixed order, you can use ORDER BY FIELD :
SELECT * FROM events
WHERE id IN (4, 5, 9, 11)
ORDER BY FIELD (id, 11, 4, 9, 5)

Group 2 and 2 values together in MySQL

Lets say we have a query
SELECT recordType,SUM(amount) FROM records GROUP BY recordType
Output
1: 50
2: 100
3: 150
4: 200
We have 4 different record types which are 1,2,3 and 4. The above query will obviously return values grouped for those 4 types. How can I adjust the query to show grouping based on their paired grouping. Like return the result of recordType 1 and recordType 2 in one row, and for 3 and 4 in second row.
Expected Output
Group 1: 150
Group 2: 350
Like return the result of recordType 1 and recordType 2 in one row, and for 3 and 4 in second row.
You could do this with a case statement. It won't perform very well, but it'll work. Depending on your actual values, the final query could look something like this:
group by case
when type in(1, 2) then 1
when type in(3, 4) then 2
when ...
else ...
end
Part of the problem is doing the grouping correctly, the other part is getting the names of the groups.
If you really have the numbers in question, you can do:
select concat('Group ', cast((recordType - 1)/2 as int)), count(*)
from records r
group by cast((recordType - 1)/2 as int)
If the values are actually not so arithmetically amenable, then a variable is possibly the simplest method:
select concat('Group ', #rn := #rn + 1), count(*)
from records r cross join (select #rn := 0) const
group by (case when type in (1, 2) then 1
when type in (3, 4) then 2
end)

Get list of IDs not present in table

Say I have a list of ids, e.g. (1, 3, 9, 2, 4, 86), and a table with a column id. I want to find all of the numbers in my list where there is not a matching row.
i.e. if the mysql table was like this:
id letter
1 a
2 b
3 c
4 d
5 e
6 f
7 g
And I have the list (1, 3, 9, 2, 4, 86), I want a query that will return (9, 86).
The only thing I can think of, is to build a really big virtual table, like:
select 1 as n union select 3 as n union select 9 as n union ....
Which I can then join against. Is there a better way? I would like to be able to do this all within mysql. As a side note (although I don't expect it to be relevant), my table has around 10,000 rows, and the list I'm using has ~100 numbers in it.
You have to first create a table that will contain the elements of the LIST
i.e (1, 3, 9, 2, 4, 86)
create table t
(
num int
)
insert into t
values
(1),(3),(9),(2),(4),(86)
Now you can use NOT IN
SELECT num
FROM t
WHERE num not in (select id from letter_table);
SQL Fiddle
From Comments.
Edit:
There is a way in which you don't have to create a table
select N from
(select 1 as N
union all
select 3 as N
union all
select 9 as N
union all
select 2 as N
union all
select 4 as N
union all
select 86 as N)t1
where t1.N
not in (select id from letter_table)
Please refer the New SQL Fiddle.
I think OP want's the Edited Part.
P.S. Make Sure table t1 doesn't exists in your DB
Create a table which contains IDs and than you can do it eaasily. See a demonstration here
SELECT
S.id,
'' AS `letter`
FROM sequence S
WHERE S.id NOT IN(SELECT
id
FROM mytable)
SQL Fiddle Demo
Assuming you use the temp table or the UNION method in #Luv's answer, consider replacing the NOT IN with an outer join as it'll likely perform better (test with your actual environment & data, of course):
SELECT num
FROM t
LEFT OUTER JOIN letter_table
ON t.num = letter_table.id
WHERE letter_table.id IS NULL;
If you use the UNION method, replace FROM t with FROM ([big UNION here]) t.