I have two table, rates and criterias. parent_id in criterias refers to id in rates.
I need to select the rates where ALL children rows in table criterias WHERE criteria_1 AND criteria_2 equal to NULL.
In the example below, only flat rate should be selected
rates
id | name
--------------------
1 | summer rate
2 | flat rate
3 | student rate
conditions
id | parent_id | criteria_1 | criteria_2
------------------------------------------------------
1 | 1 | 523 | 563
2 | 1 | null | null
3 | 2 | null | null
4 | 2 | null | null
5 | 3 | 777 | null
I tried NOT EXIST, but it return it return any rate where one children have two null criteria
try using this subquery with inner join.
select * from
(select * from rates where name = 'flat rate') t1
inner join
(select * from criterias where coalesce(criteria_1, 0) = 0 and coalesce(criteria_2, 0) = 0) t2
on t2.parent_id = t1.id
Please see the following query it should work. You need to compare 2 result set to find rate with ALL null childrens.
SELECT
a.parent_id
FROM(
SELECT
parent_id,
COUNT(*) AS total_count
FROM criterias c
WHERE c. criteria_1 IS NULL AND c.criteria_2 IS NULL
GROUP BY 1
) a
INNER JOIN (
SELECT
parent_id,
COUNT(*) AS total_count
FROM criterias c
GROUP BY 1
)b ON a.parent_id = b.parent_id AND a.total_count = b.total_count
I would use some aggregate function with an having clause grouped by parent_id.
Using a min or max would return a numerical value if there is at least one non-null value per parent_id but will be null if there are only null. So just need to use an having min(<field>) is null to find a parent_id with only null value.
select *
from rates r
where id in(
select parent_id
from criterias
group by parent_id
having min(criteria_1) is null
and min(criteria_2) is null
);
or With an inner join (if you prefer)
select *
from rates r
inner join (
select parent_id
from criterias
group by parent_id
having min(criteria_1) is null
and min(criteria_2) is null
) c ON c.parent_id = r.id;
Validated with :
create table rates(
id int,
name varchar(20)
);
create table criterias (
id int,
parent_id int,
criteria_1 int null,
criteria_2 int null
);
insert into rates values (1, 'summer rate');
insert into rates values (2, 'flate rate');
insert into rates values (3, 'student rate');
insert into rates values (4, 'old rate');
insert into rates values (5, 'any rate');
insert into criterias values (1, 1, 523, 563);
insert into criterias values (2, 1, null, null);
insert into criterias values (3, 2, null, null);
insert into criterias values (4, 2, null, null);
insert into criterias values (5, 1, 777, null);
insert into criterias values (6, 4, null, null);
insert into criterias values (7, 5, null, null);
insert into criterias values (8, 5, null, null);
/*insert into criterias values (9, 5, 1, null);*/
select *
from rates r
where id in(
select parent_id
from criterias
group by parent_id
having min(criteria_1) is null
and min(criteria_2) is null
);
Result:
id name
2 flate rate
4 old rate
5 any rate
Related
I have a JSON_ARRAY of ids in the form of [1,3,...]. Each value represents an id to a value in another table.
Table: pets
id | value
1 | cat
2 | dog
3 | hamster
Table: pet_owner
id | pets_array
1 | [1, 3]
2 | [2]
3 | []
What I want to get when I query pet_owners is the following result:
Table: pet_owner
id | pets_array
1 | ["cat", "hamster"]
2 | ["dog"]
3 | []
How do I run a sub-select on each array element to get its value?
As JSON goes, it is always a pain to handle
When you need also all that have no pets, you must left Join the owner table
CREATE TABLE pet_owner (
`id` INTEGER,
`pets_array` JSON
);
INSERT INTO pet_owner
(`id`, `pets_array`)
VALUES
('1', '[1, 3]'),
('2', '[2]'),
('3', '[]');
CREATE TABLE pets (
`id` INTEGER,
`value` VARCHAR(7)
);
INSERT INTO pets
(`id`, `value`)
VALUES
('1', 'cat'),
('2', 'dog'),
('3', 'hamster');
SELECT
t1.id,
JSON_ARRAYAGG(
p.`value`
) AS pets_array
FROM(
SELECT *
FROM pet_owner ,
JSON_TABLE(
pet_owner.pets_array , "$[*]"
COLUMNS(IDs int PATH "$" NULL ON ERROR DEFAULT '0' ON EMPTY )
) AS J_LINK ) t1
LEFT JOIN pets p ON p.id =t1.IDs
GROUP BY
t1.id
;
id | pets_array
-: | :-----------------
1 | ["cat", "hamster"]
2 | ["dog"]
db<>fiddle here
A normalized Table would spare you to convert the data into usable columns.
You can join on json_contains(), then re-aggregate:
select po.id, json_arrayagg(p.value) as owners
from pet_owner po
left join pets p on json_contains(po.pets_array, cast(p.id as char))
group by po.id
Note that, unlike most (if not all!) other databases, MySQL does not guarantee the ordering of elements in an array generated by json_arrayagg(): that's just a fact we have to live with as of the current version.
Consider a table "users" as below:
id, add_id, add
1, 1, abc
2, null, abc
3, null, xyz
4, 2, xyz
Expected output:
id, add_id, add
1, 1, abc
2, 1, abc
3, 2, xyz
4, 2, xyz
Please suggest a MySQL query to get the desired result.
A simple method uses window functions:
select id, max(add_id) over (partition by add), add
from t;
If you want to change the value, then the update would be:
update t join
(select add, max(add_id) as add_id
from t
group by add
) tt
on t.add = tt.add
set t.add_id = tt.add_id
where t.add_id is null;
You can select the id From the table.
if you have more than 1 row with and aff_id and add, then you must LIMIT the inner SELECT
CREATE TABLE table1 (
`id` INTEGER,
`add_id` VARCHAR(4),
`add` VARCHAR(3)
);
INSERT INTO table1
(`id`, `add_id`, `add`)
VALUES
('1', '1', 'abc'),
('2', null, 'abc'),
('3', null, 'xyz'),
('4', '2', 'xyz');
UPDATE table1 t2
SET `add_id` = (SELECT `add_id` FROM (SELECT * FROM table1) t1 WHERE t1. `add` = t2.`add` AND `add_id` IS NOT NULL)
WHERE `add_id` IS NULL
SELECT * FROM table1
id | add_id | add
-: | :----- | :--
1 | 1 | abc
2 | 1 | abc
3 | 2 | xyz
4 | 2 | xyz
db<>fiddle here
I have two tables. I need to join these two tables and retrieve latest status from execution table. How can I retrieve?
My schema and data:
CREATE TABLE test
(`id` serial primary key, `ref_id` int, `ref_name` varchar(7))
;
INSERT INTO test
(`id`, `ref_id`, `ref_name`)
VALUES
(1, 1, 'trial'),
(2, 3, 'test'),
(3, 7, 'testing')
;
CREATE TABLE execution
(`id` serial primary key, `ref_id` int, `status` varchar(11))
;
INSERT INTO execution
(`id`, `ref_id`, `status`)
VALUES
(1, 1, 'Completed'),
(2, 2, 'Completed'),
(3, 1, 'Completed'),
(4, 3, 'In progress'),
(5, 3, 'To do'),
(6, 2, 'In progress'),
(7, 1, 'Completed'),
(7, 1, 'To do')
;
Expected result is here below.
ref_id | ref_name | status |
3 | testing | In progress |
2 | test | To do |
1 | trial | To do |
I have tried with below query:
SELECT
ref_id,
ref_name,
status
FROM
test
JOIN execution ON test.ref_id = execution.ref_id
GROUP BY `ref_id`
ORDER BY `ref_id` DESC;
This query retrieves the status, but the retrieved status is not a latest one. How can retrieve the latest status by joining these two tables.
you can use below query
select T2.ref_id,T2.ref_name,OE.status from
(
select t1.ref_id,t1.ref_name,e.id from test t1 inner join
(select max(id) as id,ref_id from execution group by ref_id) as e
on
t1.ref_id=e.ref_id
) as T2
inner join execution OE on T2.id=OE.id
https://www.db-fiddle.com/f/rvnm8APX27dmW9a84JkCsS/1
It seems you have given in-correct data as an example as ref_id 7 not found in
execution table. However this might help you
SELECT b.ref_id,
b.ref_name,
a.status
FROM execution a
JOIN (SELECT MAX(id) id ,ref_id
FROM execution
GROUP BY ref_id) a1
USING(id,ref_id)
JOIN test b ON a.ref_id = b.ref_id ORDER BY ref_id DESC;
I am using events.I would like to know how to calculate sum in event or using single query
http://sqlfiddle.com/#!9/ad6d1c/1
DDL for question:
CREATE TABLE `table1` (
`id` int(11) NOT NULL,
`group_id` int(11) NOT NULL DEFAULT '0',
`in_use` tinyint(1) NOT NULL DEFAULT '1' COMMENT '0->in_use,1->not_in_use',
`auto_assign` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0->Yes,1->No'
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE `table1`
ADD PRIMARY KEY (`id`);
ALTER TABLE `table1`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
INSERT INTO `table1` (`id`, `group_id`, `in_use`, `auto_assign`) VALUES
(1, 3, 1, 0),(2, 2, 0,1),(3, 1, 1, 1),(4, 3, 1, 0),(5, 3, 0, 0),(6, 3, 0, 1),
(7, 3, 1, 0),(8, 3, 0, 1),(9, 3, 0, 1),(10, 3, 0, 1),(11, 3, 0, 1),(12, 3, 1, 1),
(13, 3, 1, 0),(14, 3, 0, 0),(15, 3, 0, 0),(16, 3, 0, 0),(17, 3, 0, 0),(18, 3, 1, 1),
(19, 3, 0, 0),(20, 3, 0, 0)
Expected Output :
| count | in_use | auto_assign | sum | check_count |
|-------|--------|-------------|------|------------ |
| 7 | 0 | 0 | 11 | 5 |
| 5 | 0 | 1 | 07 | 3 |
| 4 | 1 | 0 | 11 | 5 |
| 2 | 1 | 1 | 07 | 3 |
Here we can see that auto_assign=0 have total 11 count(7+4) and
auto_assign=1 have 7 count(5+2) this count should be stored into new column sum.
check_count column is percentage value of sum column.Percentage will be predefined.
Lets take 50%, So count 11(sum column value) ->50% = 5.5 = ROUND(5.5) == 5(In integer). Same way count 7(sum column value)->50% = 3.5 =ROUND(3.5)=3(Integer)
Here 5 > 4(auto_assign=0 and in_use=1 ).So have to insert record into another table(table2). if not then not.
Same way, If 3 >2 then also need to insert record into another table(table2).if not then not.
Note : This logic I would like to implement in event
This is bit complicated, but please suggest me how to do this in event.
Detail clarification :
here percentage_Value is 5 for auto_assign =0.But auto_assign=0 and in_use=1 have count is 4 which less than 5 ,then have to insert record into table 2.
suppose,if we get count is 6 for auto_assign=0 and in_use=1 ,Then no need to insert record into table2.
Same way,
here percentage_Value is 3 for auto_assign =1.But auto_assign=1 and in_use=1 have count is 2 which less than 3 ,then have to insert record into table 2.
suppose,if we get count is 4 for auto_assign=1 and in_use=1 ,Then no need to insert record into table2.
Insert query into table2:
Insert into table2(cli_group_id,auto_assign,percentage_value,result_value) values(3,0,5,4)
DEMO Fiddle
Break the problem down: we need a count of the records by auto_Assigns; so we generate a derived table (B) with that value and join back to your base table on auto_Assign. This then gives us the column we need for some and we use the truncate function and a division model to get the check_count
SELECT count(*), in_use, A.Auto_Assign, B.SumC, truncate(B.SumC/2,0) as check_Count
FROM table1 A
INNER JOIN (Select Auto_Assign, count(*) sumC
from table1
where Group_ID = 3
Group by Auto_Assign) B
on A.Auto_Assign = B.Auto_Assign
WHERE GROUP_ID = 3
Group by in_use, A.Auto_Assign
we can eliminate the double where clause by joining on it:
SELECT count(*), in_use, A.Auto_Assign, B.SumC, truncate(B.SumC/2,0) as check_Count
FROM table1 A
INNER JOIN (Select Auto_Assign, count(*) sumC, Group_ID
from table1
where Group_ID = 3
Group by Auto_Assign, Group_ID) B
on A.Auto_Assign = B.Auto_Assign
and A.Group_ID = B.Group_ID
Group by in_use, A.Auto_Assign
I'd need clarification on the rest of the question: I'm not sure what 5 > 4 your'e looking at and I see no 3 other than the check count but that's not "the same way" so I'm not sure what you're after.
Here 5 > 4(auto_assign=0 and in_use=1 ).So have to insert record into another table(table2). if not then not.
Same way, If 3 >2 then also need to insert record into another table(table2).if not then not.
Note : This logic I would like to implement in event
This is bit complicated, but please suggest me how to do this in event.
So to create the event: DOCS
Which results in:
CREATE EVENT myevent
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 6 Minutes
DO
INSERT INTO table2
SELECT count(*) as mCount
, in_use
, A.Auto_Assign
, B.SumC, truncate(B.SumC/2,0) as check_Count
FROM table1 A
INNER JOIN (SELECT Auto_Assign, count(*) sumC, Group_ID
FROM table1
WHERE Group_ID = 3
GROUP BY Auto_Assign, Group_ID) B
ON A.Auto_Assign = B.Auto_Assign
AND A.Group_ID = B.Group_ID
GROUP BY in_use, A.Auto_Assign
I know how to get the Max ID. That's easy. But I have a situation where the MaxID COULD be the row that has a value of 1. Example.. I have the following tables:
CREATE TEMPORARY TABLE people (
id INT NOT NULL
,NAME VARCHAR(50) NOT NULL
);
INSERT INTO people (id, NAME) VALUES (1, 'tony');
INSERT INTO people (id, NAME) VALUES (2, 'dave');
INSERT INTO people (id, NAME) VALUES (3, 'dan');
CREATE TEMPORARY TABLE orders (
id INT NOT NULL
,peopleid INT NOT NULL
,VALUE INT
);
INSERT INTO orders (id, peopleid, VALUE) VALUES (1, 1, NULL);
INSERT INTO orders (id, peopleid, VALUE) VALUES (2, 1, 1);
INSERT INTO orders (id, peopleid, VALUE) VALUES (3, 1, NULL);
INSERT INTO orders (id, peopleid, VALUE) VALUES (4, 2, NULL);
INSERT INTO orders (id, peopleid, VALUE) VALUES (5, 2, NULL);
INSERT INTO orders (id, peopleid, VALUE) VALUES (6, 2, NULL);
INSERT INTO orders (id, peopleid, VALUE) VALUES (7, 2, NULL);
INSERT INTO orders (id, peopleid, VALUE) VALUES (8, 1, NULL);
INSERT INTO orders (id, peopleid, VALUE) VALUES (9, 2, NULL);
which when I run the query:
SELECT * FROM people AS p
LEFT JOIN orders AS o ON o.peopleid = p.id
I get the result:
id name id peopleid value
1 tony 1 1 null
1 tony 2 1 1
1 tony 3 1 null
1 tony 8 1 null
2 dave 4 2 null
2 dave 5 2 null
2 dave 6 2 null
2 dave 7 2 null
2 dave 9 2 null
3 dan null null null
I need the result
id name id peopleid value
1 tony 2 1 1
2 dave 9 2 null
3 dan null null null
SELECT id FROM tablename
ORDER BY value=1 DESC, id DESC
LIMIT 1;
SELECT persons.personid,persons.name,othertable.id
FROM persons
LEFT JOIN othertable
ON othertable.personid = persons.personid
LEFT JOIN othertable check
ON check.personid = persons.personid
ON check.id > othertable.id
AND (othertable.value!=1 OR check.value=1)
WHERE check.personid IS NULL;
Final:
SELECT people.id,people.NAME,orders.id,orders.VALUE
FROM people
LEFT JOIN orders
ON orders.peopleid = people.id
LEFT JOIN orders checkbigger
ON checkbigger.peopleid = people.id
AND (
(
checkbigger.id > orders.id
AND orders.value <=> checkbigger.value
)
OR
(
orders.value IS NULL AND checkbigger.value IS NOT NULL
)
)
WHERE checkbigger.id IS NULL;
This will work without using LIMIT. If there are no value = 1 rows, the first MAX will be null so the COALESCE returns the second MAX. If there are value = 1 rows, the first MAX will be non-null so it gets returned.
SELECT
COALESCE(
MAX(CASE WHEN value = 1 THEN id END),
MAX(CASE WHEN value IS NULL THEN id END))
FROM a