I have two tables, first table is:
docs
and another table:
doc_val
with doc_id
as foreign key from table docs
I need to get list of docs
(including val
, type
and criteria
from doc_val
) which matches certain conditions, say for example: doc_val.criteria = 'L' and docs.rev = 1
While getting this list of docs I also need to make sure that the doc_val.val
for given doc_id
is the minimum. AND also make sure that doc_val.type = 'D'
, given that the there exists doc_val.type = 'D'
ELSE we should just simply get doc_val
for given doc_id
which has minimum doc_val.val
.
CREATE TABLE IF NOT EXISTS `docs` (
`id` int(6) unsigned NOT NULL,
`rev` int(3) unsigned NOT NULL,
`content` varchar(200) NOT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `doc_val` (
`id` int(6) unsigned NOT NULL,
`doc_id` int(6) unsigned NOT NULL,
`val` int(3) unsigned NOT NULL,
`type` varchar(2) NOT NULL,
`criteria` varchar(2) NOT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
INSERT INTO `docs` (`id`, `rev`, `content`) VALUES
('1', '1', 'The earth is flat'),
('2', '1', 'One hundred angels can dance on the head of a pin'),
('3', '1', 'The earth is flat and rests on a bull\'s horn'),
('4', '4', 'The earth is like a ball.');
INSERT INTO `doc_val` (`id`, `doc_id`, `val`, `type`, `criteria`) VALUES
('1', '1', 100, 'D', 'L'),
('2', '1', 101, 'D', 'L'),
('3', '1', 80, 'H', 'L'),
('4', '2', 10, 'H', 'S'),
('5', '2', 90, 'H', 'L'),
('6', '3', 100, 'D', 'L'),
('7', '3', 100, 'D', 'L');
With this query if I take b.type = 'D'
simply as part of where condition, I loose all docs which do not have type as D.
SELECT a.id, a.rev, a.content, b.val, b.type, b.criteria
FROM `docs` a
JOIN `doc_val` b ON b.doc_id = a.id
WHERE a.`rev` = 1 and b.type = 'D' and b.criteria = 'L'
GROUP BY `a`.`id`
HAVING min(b.`val`)
If we do not consider type=D
as condition at all, the output for this condition kind of worked but,
SELECT a.id, a.rev, a.content, b.val, b.type, b.criteria
FROM `docs` a
JOIN `doc_val` b ON b.doc_id = a.id
WHERE a.`rev` = 1 and b.criteria = 'L'
GROUP BY `a`.`id`
HAVING min(b.`val`)
final expected output:
But Technically without type=D
as condition, I should have received an output for doc.id = 1
as:
So I am probably doing something wrong with use of HAVING
any direction would be helpful.
Is it possible to prioritize doc_val.type
with doc_val.type = D
, such that when a row with type = D
it takes priority, if it doesn't exist simply take one with minimum value without considering type
?
You can try below -
DEMO
SELECT
*
FROM
(SELECT
a.id, a.rev, a.content, MIN(b.val) val, b.type, b.criteria
FROM
`docs` a
JOIN `doc_val` b ON b.doc_id = a.id
WHERE
a.`rev` = 1 AND b.criteria = 'L'
GROUP BY a.id , a.rev , a.content , b.type , b.criteria) A
WHERE
val IN (SELECT
MAX(val)
FROM
(SELECT
a.id, a.rev, a.content, MIN(b.val) val, b.type, b.criteria
FROM
`docs` a
JOIN `doc_val` b ON b.doc_id = a.id
WHERE
a.`rev` = 1 AND b.criteria = 'L'
GROUP BY a.id , a.rev , a.content , b.type , b.criteria) B
WHERE
A.content = B.content)
OUTPUT:
id rev content val type criteria
1 1 The earth is flat 100 D L
2 1 One hundred angels can dance on the head of a pin 90 H L
3 1 The earth is flat and rests on a bull's horn 100 D L
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With