Please help me.
I have 2 table Users and Diseaselogs
1 user has many diseaselogs
I want to select all users and each user must be field date in diseaselogs is max
Data example
Users
id | name | age
1 | Nam | 21
2 | Thao | 23
3 | An | 19
Diseaselogs
id | logType | userId | date
1 | positive | 1 | 2021-06-21
2 | negative | 2 | 2021-06-22
3 | pending | 1 | 2021-06-24
4 | negative | 1 | 2021-06-26
5 | negative | 2 | 2021-06-21
6 | pending | 3 | 2021-06-23
7 | negative | 1 | 2021-06-24
8 | negative | 2 | 2021-06-25
9 | pending | 3 | 2021-06-28
Expect output
id | name | logId | logType | date
1 | Nam | 4 | negative | 2021-06-26
2 | Thao | 8 | negative | 2021-06-25
3 | An | 9 | pending | 2021-06-28
As ROW_NUMBER() doesn't support lower version of mysql i.e 5.7 to downwords. So I've tried here alternatives of ROW_NUMBER().
-- MySQL (V 5.6)
SELECT u.id, u.name, tmp.logId, tmp.logType, tmp.date
FROM users u
INNER JOIN (SELECT #row_no := IF(#prev_val = t.userId, #row_no + 1, 1) AS row_number
, #prev_val := t.userId AS userId
, t.date
, t.logType
, t.id AS logId
FROM Diseaselogs t,
(SELECT #row_no := 0) x,
(SELECT #prev_val := '') y
ORDER BY t.userId, t.date DESC ) tmp
ON u.id = tmp.userId
AND tmp.row_number = 1;
Please check url http://sqlfiddle.com/#!9/741b96/16
Also if your MySQL version is 5.8 then you can apply the below query where row_number() is used.
SELECT u.id, u.name, tmp.logId, tmp.logType, tmp.date
FROM users u
INNER JOIN (SELECT ROW_NUMBER() OVER (PARTITION BY userId ORDER BY date DESC) row_number
, userId
, date
, logType
, id AS logId
FROM Diseaselogs ) tmp
ON u.id = tmp.userId
AND tmp.row_number = 1;
in mysql 8 you can use ROW_NUMBER and an INNER JOIN
in prior versions you need to use another method for rownumber
Schema (MySQL v8.0)
CREATE TABLE Diseaselogs (
`id` INTEGER,
`logType` VARCHAR(8),
`userId` INTEGER,
`date` VARCHAR(10)
);
INSERT INTO Diseaselogs
(`id`, `logType`, `userId`, `date`)
VALUES
('1', 'positive', '1', '2021-06-21'),
('2', 'negative', '2', '2021-06-22'),
('3', 'pending', '1', '2021-06-24'),
('4', 'negative', '1', '2021-06-26'),
('5', 'negative', '2', '2021-06-21'),
('6', 'pending', '3', '2021-06-23'),
('7', 'negative', '1', '2021-06-24'),
('8', 'negative', '2', '2021-06-25'),
('9', 'pending', '3', '2021-06-28');
CREATE TABLE users (
`id` INTEGER,
`name` VARCHAR(4),
`age` INTEGER
);
INSERT INTO users
(`id`, `name`, `age`)
VALUES
('1', 'Nam', '21'),
('2', 'Thao', '23'),
('3', 'An', '19');
Query #1
SELECT
u.id, `name`, t1.id,`logType`, `date`
FROM
(SELECT
id,`logType`, `userId`, `date`
, ROW_NUMBER() OVER (PARTITION BY `userId` ORDER BY `date` DESC) rn
FROM
Diseaselogs) t1
INNER JOIN users u ON t1.userId = u.id
WHERE rn = 1;
id
name
id
logType
date
1
Nam
4
negative
2021-06-26
2
Thao
8
negative
2021-06-25
3
An
9
pending
2021-06-28
View on DB Fiddle
Schema (MySQL v8.0)
CREATE TABLE Diseaselogs (
`id` INTEGER,
`logType` VARCHAR(8),
`userId` INTEGER,
`date` VARCHAR(10)
);
INSERT INTO Diseaselogs
(`id`, `logType`, `userId`, `date`)
VALUES
('1', 'positive', '1', '2021-06-21'),
('2', 'negative', '2', '2021-06-22'),
('3', 'pending', '1', '2021-06-24'),
('4', 'negative', '1', '2021-06-26'),
('5', 'negative', '2', '2021-06-21'),
('6', 'pending', '3', '2021-06-23'),
('7', 'negative', '1', '2021-06-24'),
('8', 'negative', '2', '2021-06-25'),
('9', 'pending', '3', '2021-06-28');
CREATE TABLE users (
`id` INTEGER,
`name` VARCHAR(4),
`age` INTEGER
);
INSERT INTO users
(`id`, `name`, `age`)
VALUES
('1', 'Nam', '21'),
('2', 'Thao', '23'),
('3', 'An', '19');
Query #1
SELECT
u.id, `name`, `age`,`logType`, `date`
FROM
(SELECT
`logType`, `userId`, `date`
, ROW_NUMBER() OVER (PARTITION BY `userId` ORDER BY `date` DESC) rn
FROM
Diseaselogs) t1
INNER JOIN users u ON t1.userId = u.id
WHERE rn = 1;
id
name
age
logType
date
1
Nam
21
negative
2021-06-26
2
Thao
23
negative
2021-06-25
3
An
19
pending
2021-06-28
View on DB Fiddle
Related
i have 2 tables (tbl_news and tbl_news_category)
tbl_news_category table is
cat_id cat_name general
1 name1 1
2 name2 1
3 name3 0
4 name4 1
5 name5 0
tbl_news table is
id cat_id title news_isimage
1 2 title1 1
2 5 title2 0
3 1 title2 1
4 3 title2 1
5 2 title2 1
6 5 title2 1
7 4 title2 1
8 5 title2 1
i want to get 5 random items from tbl_news which general value should be 1
i tried below code and its not working
SELECT
d.*
FROM
tbl_news d,
tbl_news_category p
WHERE
p.general = 1 AND d.news_isimage = 0
AND d.cat_id > 3
ORDER BY RAND()
LIMIT 5
but its giving news item with cat_id with general = 0
Do a proper join of the tables:
select n.*
from tbl_news n inner join tbl_news_category c
on c.cat_id = n.cat_id
where c.general = 1
order by rand() limit 5
You have also in your code the conditions:
news_isimage = 0 AND cat_id > 3
If you need them you can add them to the WHERE clause:
WHERE c.general = 1 AND n.news_isimage = 0 AND c.cat_id > 3
There is no data for your query available.
But do an INNER JOIN
CREATE TABLE tbl_news (
`id` INTEGER,
`cat_id` INTEGER,
`title` VARCHAR(6),
`news_isimage` INTEGER
);
INSERT INTO tbl_news
(`id`, `cat_id`, `title`, `news_isimage`)
VALUES
('1', '2', 'title1', '1'),
('2', '5', 'title2', '0'),
('3', '1', 'title2', '1'),
('4', '3', 'title2', '1'),
('5', '2', 'title2', '1'),
('6', '5', 'title2', '1'),
('7', '4', 'title2', '1'),
('8', '5', 'title2', '1');
CREATE TABLE tbl_news_category (
`cat_id` INTEGER,
`cat_name` VARCHAR(5),
`general` INTEGER
);
INSERT INTO tbl_news_category
(`cat_id`, `cat_name`, `general`)
VALUES
('1', 'name1', '1'),
('2', 'name2', '1'),
('3', 'name3', '0'),
('4', 'name4', '1'),
('5', 'name5', '0');
✓
✓
✓
✓
SELECT
tn.title
, tn.news_isimage
,tnc.cat_name
FROM tbl_news tn INNER JOIN tbl_news_category tnc ON tn.cat_id = tnc.cat_id
WHERE
tnc.general = 1
AND tn.news_isimage = 0
AND tnc.cat_id > 3
ORDER BY RAND()
LIMIT 5
title | news_isimage | cat_name
:---- | -----------: | :-------
db<>fiddle here
MySQL 5.7
Consider the following sample data:
CREATE TABLE catalog_product_entity_media_gallery (
`value` VARCHAR(24),
`entity_id` INTEGER
);
INSERT INTO catalog_product_entity_media_gallery
(`value`, `entity_id`)
VALUES
('a01-some-item-p1-png.png', '1'),
('a01-some-item-p2-png.png', '1'),
('a01-some-item-d1-png.png', '1'),
('a01-some-item-d5-png.png', '1'),
('another-transparent.png', '2'),
('another-back.png', '2'),
('another-front.png', '2'),
('another-side.png', '2');
CREATE TABLE catalog_product_entity (
`entity_id` INTEGER,
`sku` VARCHAR(3)
);
INSERT INTO catalog_product_entity
(`entity_id`, `sku`)
VALUES
('1', 'a01'),
('2', 'b22');
CREATE TABLE catalog_product_entity_varchar (
`attribute_id` INTEGER,
`value` VARCHAR(24)
);
INSERT INTO catalog_product_entity_varchar
(`attribute_id`, `value`)
VALUES
('85', 'a01-some-item-p1-png.png'),
('85', 'another-transparent.png');
DB Fiddle of same: https://www.db-fiddle.com/f/7fAx1waY3TwjR34PanBkkv/0
With the query below, I get the following result:
select
a.value as 'original_file_name',
b.sku,
if(isnull(c.attribute_id), 0, 1) as 'is_default',
concat(sku, '_', if(isnull(c.attribute_id), concat('slideshow_', 'x'), 'default_1'), '.', substring_index(a.value, "." , -1)) as 'new_file_name'
from catalog_product_entity_media_gallery a
join catalog_product_entity b on b.entity_id = a.entity_id
left join catalog_product_entity_varchar c on c.attribute_id = 85 and c.value = a.value
order by sku, is_default desc;
+--------------------------+-----+------------+---------------------+
| original_file_name | sku | is_default | new_file_name |
+--------------------------+-----+------------+---------------------+
| a01-some-item-p1-png.png | a01 | 1 | a01_default_1.png |
| a01-some-item-p2-png.png | a01 | 0 | a01_slideshow_x.png |
| a01-some-item-d1-png.png | a01 | 0 | a01_slideshow_x.png |
| a01-some-item-d5-png.png | a01 | 0 | a01_slideshow_x.png |
| another-transparent.png | b22 | 1 | b22_default_1.png |
| another-back.png | b22 | 0 | b22_slideshow_x.png |
| another-front.png | b22 | 0 | b22_slideshow_x.png |
| another-side.png | b22 | 0 | b22_slideshow_x.png |
+--------------------------+-----+------------+---------------------+
In the new_file_name column, I want to insert an ordinal number in place of x. It should start at 1 for every new sku.
Wanted result:
a01_default_1.png
a01_slideshow_1.png
a01_slideshow_2.png
a01_slideshow_3.png
b22_default_1.png
b22_slideshow_1.png
b22_slideshow_2.png
b22_slideshow_3.png
Kindly try it
;with cte as (
select a.*,ROW_NUMBER() over (partition by new_file_name order by ID) as ROWNUMBER
from catalog_product_entity_media_gallery a
)
select concat(a.new_file_name,'_',ROWNUMBER) from cte
Using a variable that holds a number that increments for every row.
When is_default = 1, the number gets reset.
drop temporary table if exists pictures;
create temporary table pictures
select
a.entity_id,
a.value as original_file_name,
b.sku as sku,
if(isnull(d.attribute_id), 0, 1) as is_default,
substring_index(a.value, "." , -1) as file_extension
from catalog_product_entity_media_gallery a
join catalog_product_entity b on b.entity_id = a.entity_id
left join catalog_product_entity_varchar d on d.attribute_id = 85 and d.value = a.value
order by sku, is_default desc;
set #number = 0;
select
original_file_name,
sku,
is_default,
case
when
is_default = 0
then
#number := #number + 1
else #number := 0
end as number,
concat(sku, '_', if(is_default, 'default_1', concat('slideshow_', #number)), '.', file_extension) as new_file_name
from pictures;
I have three tables to keep track of emails and their assigned categories: Email keeps the mail's content, Category lists the categories and Classification links an Email entry ID with a Category entry ID. Schema with sample data and query is available on SQLFiddle: http://sqlfiddle.com/#!9/a410a6/26/0
CREATE TABLE `Category` (
`id` int(6) unsigned NOT NULL,
`name` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
CREATE TABLE `Mail` (
`id` int(6) unsigned NOT NULL,
`content` varchar(500) NOT NULL,
`date` datetime NOT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
CREATE TABLE `Classification` (
`id` int(6) unsigned NOT NULL,
`mail_id` int(6) unsigned NOT NULL,
`category_id` int(6) unsigned NOT NULL,
FOREIGN KEY (mail_id) REFERENCES Mail(id),
FOREIGN KEY (category_id) REFERENCES Category(id),
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
INSERT INTO `Category` (`id`, `name`) VALUES
('1', 'Important'),
('2', 'Urgent'),
('3', 'Normal');
INSERT INTO `Mail` (`id`, `content`, `date`) VALUES
('1', 'Important Email', '2019-01-04T13:53:52'),
('2', 'Urgent Email', '2019-01-19T13:53:52'),
('3', 'Very Urgent Email', '2019-01-24T13:53:52'),
('4', 'Quite Urgent Email', '2019-01-24T13:53:52'),
('5', 'Normal Email', '2019-01-21T13:53:52'),
('6', 'Regular Email', '2019-01-14T13:53:52'),
('7', 'Regular Email', '2019-01-23T13:53:52'),
('8', 'Regular Email', '2019-01-23T13:53:52'),
('9', 'Regular Email', '2019-01-20T13:53:52'),
('10', 'Very Urgent Email', '2019-01-25T13:53:52'),
('11', 'Very Urgent Email', '2019-01-25T13:53:52');
INSERT INTO `Classification` (`id`, `mail_id`, `category_id`) VALUES
('1', '1', '1'),
('2', '2', '2'),
('3', '3', '2'),
('4', '4', '2'),
('5', '5', '3'),
('6', '6', '3'),
('7', '6', '3'),
('8', '6', '3'),
('9', '6', '3'),
('10', '6', '2'),
('11', '6', '2');
I want to return the number of mails received for each category for each date recorded, i.e. my expected results would be
+----------------------+-----------+----------+
| date | name | count(*) |
+----------------------+-----------+----------+
| 2019-01-04T13:53:52Z | Important | 1 |
| 2019-01-14T13:53:52Z | Normal | 1 |
| 2019-01-19T13:53:52Z | Urgent | 1 |
| 2019-01-20T13:53:52Z | Normal | 1 |
| 2019-01-21T13:53:52Z | Normal | 1 |
| 2019-01-23T13:53:52Z | Normal | 2 |
| 2019-01-24T13:53:52Z | Urgent | 1 |
| 2019-01-25T13:53:52Z | Urgent | 2 |
+----------------------+-----------+----------+
To do so I run the following query with a double groupby, filtering on the Classification table:
SELECT Mail.date, Category.name, count(*) FROM Mail, Classification, Category WHERE Category.id = Classification.category_id AND Classification.mail_id = Mail.id GROUP BY Mail.date, Category.name
Which gives me the following results:
+----------------------+-----------+----------+
| date | name | count(*) |
+----------------------+-----------+----------+
| 2019-01-04T13:53:52Z | Important | 1 |
| 2019-01-14T13:53:52Z | Normal | 4 |
| 2019-01-14T13:53:52Z | Urgent | 2 |
| 2019-01-19T13:53:52Z | Urgent | 1 |
| 2019-01-21T13:53:52Z | Normal | 1 |
| 2019-01-24T13:53:52Z | Urgent | 2 |
+----------------------+-----------+----------+
Which is entirely wrong.
I've tried substituting the WHERE statement for a JOIN:
SELECT Mail.date, Category.name, count(*) FROM (Mail, Category) RIGHT JOIN Classification ON Category.id = Classification.category_id AND Classification.mail_id = Mail.id GROUP BY Mail.date, Category.name `
But I get the exact same results as above.
Why are those queries returning these erroneous results and what should I do to fix them ?
First, your query should look like this:
SELECT m.date, c.name, count(*)
FROM Mail m JOIN
Classification cl
ON cl.mail_id = m.id JOIN
Category c
ON c.id = cl.category_id
GROUP BY m.date, c.name ;
Now that we have gotten that out of the way, your problem is that emails have multiple categories. So, they are multiply counted. Hence, the results you are getting are correct.
You have exact duplicates in the classification table, so a simple solution is:
SELECT m.date, c.name, count(distinct m.id)
FROM Mail m JOIN
Classification cl
ON cl.mail_id = m.id JOIN
Category c
ON c.id = cl.category_id
GROUP BY m.date, c.name ;
That said, the real solution is to fix your data, so it doesn't have duplicates.
Here is the SQL Fiddle using your data. You have a "2" for emails on 2019-01-23. However, there are no classified emails on that date, so they are not in the results.
I have a table which looks like this,
+-----+--------+-------+
| num | amount | value |
+-----+--------+-------+
| 1 | 12 | 1 |
| 1 | 12 | 1 |
| 2 | 13 | 1 |
| 4 | 15 | 0 |
| 2 | 13 | 1 |
| 3 | 14 | 1 |
| 3 | 14 | 1 |
| 1 | 12 | 1 |
+-----+--------+-------+
I want to sum the 'amount' column based on distinct 'num' column where 'value' is equal to 1,
for example, after running following query,
select DISTINCT num, amount, value from test where value =1 ;
distinct 'num' based table is
+-----+--------+-------+
| num | amount | value |
+-----+--------+-------+
| 1 | 12 | 1 |
| 2 | 13 | 1 |
| 3 | 14 | 1 |
+-----+--------+-------+
so i want the final result to be
12+13+14 = 39.
one more thing is that
i cant use subquery.
because it is already part of another query as well.
here is the script of my table is
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `test`
-- ----------------------------
DROP TABLE IF EXISTS `test`;
CREATE TABLE `test` (
`num` int(11) DEFAULT NULL,
`amount` int(11) DEFAULT NULL,
`value` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-- ----------------------------
-- Records of test
-- ----------------------------
INSERT INTO `test` VALUES ('1', '12', '1');
INSERT INTO `test` VALUES ('1', '12', '1');
INSERT INTO `test` VALUES ('2', '13', '1');
INSERT INTO `test` VALUES ('4', '15', '0');
INSERT INTO `test` VALUES ('2', '13', '1');
INSERT INTO `test` VALUES ('3', '14', '1');
INSERT INTO `test` VALUES ('3', '14', '1');
INSERT INTO `test` VALUES ('1', '12', '1');
You can create a temp table containing distinct values and using SUM() to calculate amount. Your query will go like:
SELECT SUM(amount)
FROM (
SELECT DISTINCT t.`num`, t.`amount`
FROM test t
WHERE t.`value`=1
) temp
select num,sum(amount)/Count(*)
from test
where value = 1
group by num
order by num
I assume that every num has the same value (if not, how should you pick one?)
so, this will work:
SELECT SUM(DISTINCT amount)
FROM test
WHERE value = 1
SELECT SUM(amount) FROM (SELECT DISTINCT num, amount, VALUE FROM test WHERE VALUE =1) AS temp ;
Please check the solution
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `test`
-- ----------------------------
DROP TABLE IF EXISTS `test`;
CREATE TABLE `test` (
`num` int(11) DEFAULT NULL,
`amount` int(11) DEFAULT NULL,
`value` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-- ----------------------------
-- Records of test
-- ----------------------------
INSERT INTO `test` VALUES ('1', '12', '1');
INSERT INTO `test` VALUES ('1', '12', '1');
INSERT INTO `test` VALUES ('2', '13', '1');
INSERT INTO `test` VALUES ('4', '15', '0');
INSERT INTO `test` VALUES ('2', '13', '1');
INSERT INTO `test` VALUES ('3', '14', '1');
INSERT INTO `test` VALUES ('3', '14', '1');
INSERT INTO `test` VALUES ('1', '12', '1');
-- ----------------------------
-- Insert the result set into temp table and then use sum().
-- ----------------------------
SELECT DISTINCT `num` , `amount`
INTO #tmp
FROM test
WHERE `value` =1
SELECT * FROM #tmp
SELECT sum(`amount`) as amount FROM #tmp
As you can see on this sqlfiddle, I have this schema:
CREATE TABLE reviews
(`id` int(11) NOT NULL AUTO_INCREMENT,
`shop_id` int(11),
`order_id` char(255),
`product_id` char(32),
`review_time` int(11),
PRIMARY KEY (`id`)
)
;
INSERT INTO reviews
(`shop_id`, `order_id`, `product_id`, `review_time`)
VALUES
('10', '100', '1000', '1466190000'),
('10', '100', '1000', '1466276400'),
('10', '100', '1000', '1466462800'),
('20', '800', '8000', '1466249200')
;
CREATE TABLE tags
(`id` int(11) NOT NULL AUTO_INCREMENT,
`shop_id` int(11),
`order_id` char(255),
`product_id` char(32),
`tag_time` INT(11) NULL,
PRIMARY KEY (`id`)
)
;
INSERT INTO tags
(`shop_id`, `order_id`, `product_id`, `tag_time`)
VALUES
('10', '100', '1000', '1466449200'),
('10', '100', '1000', NULL),
('10', '100', '3000', NULL),
('20', '800', '8000', '1469449200')
;
I need to get statistics by date showing how many reviews I have per date and how many were tagged and how many were not. I'm using this query:
SELECT
DATE_FORMAT(FROM_UNIXTIME(r.`review_time`), "%d.%m.%Y") AS review_submited_on,
r.`shop_id`,
COUNT(*) as total_orders,
COUNT(*) as tagged_orders
FROM
reviews AS r
LEFT JOIN tags as t
ON r.`shop_id` = t.`shop_id` AND
r.`order_id` = t.`order_id` AND
r.`product_id` = t.`product_id`
WHERE
t.`tag_time` IS NOT NULL
GROUP BY r.`shop_id`, r.`order_id`, r.`product_id`
ORDER BY review_submited_on ASC
UPDATE
The expected result would look like this:
| review_submited_on | shop_id | total_orders | tagged_orders |
|--------------------|---------|--------------|---------------|
| 17.06.2016 | 10 | 3 | 1 |
| 18.06.2016 | 20 | 1 | 1 |
I created this sqlfiddle for demo.
Thanks for any help :)
Try this, and let me know if that is something you want.
SELECT review_submited_on, shop_id, total_orders, IFNULL(tagged_orders, 0) tagged_orders
FROM
(SELECT shop_id, COUNT(DISTINCT shop_id, order_id, product_id) total_orders, DATE_FORMAT(FROM_UNIXTIME(review_time), "%d.%m.%Y") AS review_submited_on
FROM reviews
GROUP BY shop_id) review_counter
LEFT JOIN
(SELECT shop_id, COUNT(DISTINCT shop_id, order_id, product_id) tagged_orders
FROM tags
WHERE tag_time IS NOT NULL
GROUP BY shop_id) tag_counter
USING (shop_id)
Result
| review_submited_on | shop_id | total_orders | tagged_orders |
|--------------------|---------|--------------|---------------|
| 17.06.2016 | 10 | 1 | 1 |
| 18.06.2016 | 20 | 1 | 1 |