MySql rows in to columns (but dynamic rows) - mysql

This is my SQL table and data. http://sqlfiddle.com/#!9/effe2
CREATE TABLE IF NOT EXISTS `CustomValue` (
`id` int(11) NOT NULL,
`customFieldId` int(11) NOT NULL,
`relatedId` int(11) NOT NULL,
`fieldValue` text COLLATE utf8_unicode_ci,
`createdAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `CustomValue` (`id`, `customFieldId`, `relatedId`, `fieldValue`, `createdAt`) VALUES
(1, 10, 4031, NULL, '2015-11-05 04:25:00'),
(2, 14, 4031, 'adsas#das.sadsa', '2015-11-05 04:25:00'),
(3, 13, 4031, '456', '2015-11-05 04:25:00'),
(4, 16, 4031, '2015-11-09', '2015-11-05 04:25:00'),
(5, 9, 4031, '456', '2015-11-05 04:25:00'),
(6, 11, 4031, 'dsasda', '2015-11-05 04:25:00'),
(7, 15, 4031, '1', '2015-11-05 04:25:00');
Right now it is as,
id customFieldId relatedId fieldValue createdAt
1 10 4031 (null) November, 05 2015 04:25:00
2 14 4031 adsas#das.sadsa November, 05 2015 04:25:00
3 13 4031 456 November, 05 2015 04:25:00
4 16 4031 2015-11-09 November, 05 2015 04:25:00
5 9 4031 456 November, 05 2015 04:25:00
6 11 4031 dsasda November, 05 2015 04:25:00
7 15 4031 1 November, 05 2015 04:25:00
I need to group by relatedId and and get the final output as 1 row for each relatedId.
This is the reference table.
CREATE TABLE IF NOT EXISTS `CustomField` (
`id` int(11) NOT NULL,
`customTypeId` int(11) NOT NULL,
`fieldName` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
`relatedTable` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
`defaultValue` text COLLATE utf8_unicode_ci,
`sortOrder` int(11) NOT NULL DEFAULT '0',
`enabled` char(1) COLLATE utf8_unicode_ci DEFAULT '1',
`listItemTag` char(1) COLLATE utf8_unicode_ci DEFAULT NULL,
`required` char(1) COLLATE utf8_unicode_ci DEFAULT '0',
`onCreate` char(1) COLLATE utf8_unicode_ci DEFAULT '1',
`onEdit` char(1) COLLATE utf8_unicode_ci DEFAULT '1',
`onView` char(1) COLLATE utf8_unicode_ci DEFAULT '1',
`listValues` text COLLATE utf8_unicode_ci,
`label` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
`htmlOptions` text COLLATE utf8_unicode_ci
) ENGINE=MyISAM AUTO_INCREMENT=17 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `CustomField` (`id`, `customTypeId`, `fieldName`, `relatedTable`, `defaultValue`, `sortOrder`, `enabled`, `listItemTag`, `required`, `onCreate`, `onEdit`, `onView`, `listValues`, `label`, `htmlOptions`) VALUES
(13, 1, 'HOMEEMAIL', 'people', '', 0, '1', NULL, '1', '1', '1', '1', NULL, 'Home Email', ''),
(9, 1, 'LANDPHONENO', 'people', '', 0, '1', NULL, '1', '1', '1', '1', NULL, 'Land Phone No', ''),
(10, 12, 'ABOUTME', 'people', '', 0, '1', NULL, '0', '1', '1', '1', NULL, 'About Me', ''),
(11, 3, 'PHONENUMBER2', 'people', '', 0, '1', NULL, '1', '1', '1', '1', NULL, 'Phone Number 2', ''),
(14, 3, 'ALTERNATEEMAIL', 'people', '', 0, '1', NULL, '1', '1', '1', '1', NULL, 'Alternate Email', ''),
(15, 11, 'SCHOOLING?', 'people', '', 0, '1', NULL, '1', '1', '1', '1', NULL, 'Schooling?', ''),
(16, 4, 'JOINDATE', 'people', '', 0, '1', NULL, '1', '1', '1', '1', NULL, 'Join Date', '');
The final output should be,
relatedId | Alternate Email | Home Email | Join Date | Land Phone No | Phone Number 2 | Schooling?
--------------------------------------------------------------------------------------------------
4031 | adsas#das.sadsa | 456 | 2015-11-09| 456 | dsasda | 1
relatedId | Alternate Email | Home Email | Join Date | Land Phone No | Phone Number 2 | Schooling? | Interest
--------------------------------------------------------------------------------------------------
4033 | adsas#das.sadsa | 456 | 2015-11-09| 456 | dsasda | 1 | Drawing
The output of phpmyadmin

What you need here is PIVOT rows into columns, MySQL however doesn't have a native pivot operator like SQL Server or Oracle for example. But you can use CASE expression with group by to do this like this:
SELECT
v.relatedId, v.CreatedAt,
MAX(IF(f.fieldName = 'ABOUTME', COALESCE(v.fieldValue, f.defaultValue) , NULL)) AS 'ABOUTME',
MAX(IF(f.fieldName = 'ALTERNATEEMAIL', COALESCE(v.fieldValue, f.defaultValue) , NULL)) AS 'ALTERNATEEMAIL',
MAX(IF(f.fieldName = 'HOMEEMAIL', COALESCE(v.fieldValue, f.defaultValue) , NULL)) AS 'HOMEEMAIL',
MAX(IF(f.fieldName = 'JOINDATE', COALESCE(v.fieldValue, f.defaultValue) , NULL)) AS 'JOINDATE',
MAX(IF(f.fieldName = 'LANDPHONENO', COALESCE(v.fieldValue, f.defaultValue) , NULL)) AS 'LANDPHONENO',
MAX(IF(f.fieldName = 'PHONENUMBER2', COALESCE(v.fieldValue, f.defaultValue) , NULL)) AS 'PHONENUMBER2',
MAX(IF(f.fieldName = 'SCHOOLING?', COALESCE(v.fieldValue, f.defaultValue) , NULL)) AS 'SCHOOLING?'
FROM customField AS f
INNER JOIN Customvalue AS v ON f.Id = v.customFieldId
GROUP BY v.relatedId, v.CreatedAt;
And to do it dynamically you have to do it with dynamic sql like this:
SET #Colvalues = NULL;
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT CONCAT('MAX(IF(f.fieldName = ''',
f.fieldName, ''', COALESCE(v.fieldValue, f.defaultValue) , NULL)) AS ', '''', f.fieldName , '''')
) INTO #Colvalues
FROM customField AS f
INNER JOIN Customvalue AS v ON f.Id = v.customFieldId;
SET #sql = CONCAT('SELECT
v.relatedId, v.CreatedAt, ', #Colvalues , '
FROM customField AS f
INNER JOIN Customvalue AS v ON f.Id = v.customFieldId
GROUP BY v.relatedId, v.CreatedAt;');
PREPARE stmt
FROM #sql;
EXECUTE stmt;
Note that:
If the field value is null it will set the value from the default value field, thats what COALESCE(v.fieldValue, f.defaultValue) do.
You can eliminate NULL values like in the field Aboutname case, by adding a WHERE v.fieldValue IS NOT NULL.
This will give you:

Related

LEFT JOIN select latest row from the left join

I have a company database that has all its details within it. It also has a separate table where credit ratings are stored.
DROP TABLE IF EXISTS `company`;
CREATE TABLE IF NOT EXISTS `company` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET latin1 NOT NULL,
`email` varchar(255) CHARACTER SET latin1 NOT NULL,
`address` varchar(255) NOT NULL,
`address2` text NOT NULL,
`address3` text NOT NULL,
`phone` text NOT NULL,
`contacts` text NOT NULL,
`islive` tinyint(1) NOT NULL DEFAULT '1',
`qt` tinyint(1) NOT NULL DEFAULT '30',
`pt` tinyint(1) NOT NULL DEFAULT '30',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `creditrating`;
CREATE TABLE IF NOT EXISTS `creditrating` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`cid` int(11) NOT NULL,
`rating` int(11) NOT NULL,
`arating` varchar(10) NOT NULL,
`type` tinyint(1) NOT NULL DEFAULT '1',
`thedate` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `company` (`id`, `name`, `email`, `address`, `address2`, `address3`, `phone`, `contacts`, `islive`, `qt`, `pt`) VALUES
(190, 'Test Company', 'test#test.com', 'Testing Client 1\r\nsdfsdfsdf\r\nsdfsdfsdf', 'Testing Client 1\r\nsdfsdfsdf\r\nsdfsdfsdf', 'Testing Client 1\r\nsdfsdfsdf\r\nsdfsdfsdf', '65165156', 'test name', 1, 30, 30),
(191, 'Test Company 2', 'test2#test2.com', 'Testing Client 2\r\nsdfsdfsdf\r\nsdfsdfsdf', 'Testing Client 2\r\nsdfsdfsdf\r\nsdfsdfsdf', 'Testing Client 2\r\nsdfsdfsdf\r\nsdfsdfsdf', '65165156', 'test name 2', 1, 30, 30);
INSERT INTO `creditrating` (`id`, `cid`, `rating`, `arating`, `type`, `thedate`) VALUES
(3, 190, 684, 'da774', 1, '2021-03-30 15:08:52'),
(6, 190, 222, 'DD222', 1, '2021-03-30 17:46:22');
I am trying to only retrieve the company details and only the latest row on the credit rating table.
The SQL I have got closest to getting this to work is (Mysql 5.6):
SELECT c.id
, AES_DECRYPT(c.name, 'co1') as name
, AES_DECRYPT(c.phone, 'co3') as phone
, c.islive
, r.rating
FROM company c
LEFT
JOIN creditrating r
ON (SELECT r.thedate FROM creditrating WHERE c.id=r.cid ORDER BY r.thedate DESC LIMIT 1)
DB FIDDLE HERE
At the moment it is bringing back 2 rows of the same company instead of just 1.
Thank you in advance for any pointers you guys can through my way.
prior versions don't have window functions but you can switch to user defined variables
DROP TABLE IF EXISTS `company`;
CREATE TABLE IF NOT EXISTS `company` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET latin1 NOT NULL,
`email` varchar(255) CHARACTER SET latin1 NOT NULL,
`address` varchar(255) NOT NULL,
`address2` text NOT NULL,
`address3` text NOT NULL,
`phone` text NOT NULL,
`contacts` text NOT NULL,
`islive` tinyint(1) NOT NULL DEFAULT '1',
`qt` tinyint(1) NOT NULL DEFAULT '30',
`pt` tinyint(1) NOT NULL DEFAULT '30',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `creditrating`;
CREATE TABLE IF NOT EXISTS `creditrating` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`cid` int(11) NOT NULL,
`rating` int(11) NOT NULL,
`arating` varchar(10) NOT NULL,
`type` tinyint(1) NOT NULL DEFAULT '1',
`thedate` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `company` (`id`, `name`, `email`, `address`, `address2`, `address3`, `phone`, `contacts`, `islive`, `qt`, `pt`) VALUES
(190, 'Test Company', 'test#test.com', 'Testing Client 1\r\nsdfsdfsdf\r\nsdfsdfsdf', 'Testing Client 1\r\nsdfsdfsdf\r\nsdfsdfsdf', 'Testing Client 1\r\nsdfsdfsdf\r\nsdfsdfsdf', '65165156', 'test name', 1, 30, 30),
(191, 'Test Company 2', 'test2#test2.com', 'Testing Client 2\r\nsdfsdfsdf\r\nsdfsdfsdf', 'Testing Client 2\r\nsdfsdfsdf\r\nsdfsdfsdf', 'Testing Client 2\r\nsdfsdfsdf\r\nsdfsdfsdf', '65165156', 'test name 2', 1, 30, 30);
INSERT INTO `creditrating` (`id`, `cid`, `rating`, `arating`, `type`, `thedate`) VALUES
(3, 190, 684, 'da774', 1, '2021-03-30 15:08:52'),
(6, 190, 222, 'DD222', 1, '2021-03-30 17:46:22');
SELECT
id, name, phone, islive, rating, `thedate`
FROM
(SELECT
name,
phone,
islive,
rating,
`thedate`,
IF(id = #id, #rnk:=#rnk + 1, #rnk:=1) AS rnk,
#id:=id AS id
FROM
(SELECT
c.id,
AES_DECRYPT(c.name, 'co1') AS name,
AES_DECRYPT(c.phone, 'co3') AS phone,
c.islive,
r.rating,
`thedate`
FROM
company c
LEFT JOIN creditrating r ON c.id = r.cid) t1, (SELECT #id:=- 1, #rnk:=0) t2
ORDER BY id , `thedate` DESC) t3
WHERE
rnk = 1;
id | name | phone | islive | rating | thedate
--: | :--- | :---- | -----: | -----: | :------------------
190 | null | null | 1 | 222 | 2021-03-30 17:46:22
191 | null | null | 1 | null | null
db<>fiddle here
You can use a window function for this:
SELECT c.id, AES_DECRYPT(c.name, 'co1') as name, AES_DECRYPT(c.phone, 'co3') as phone, c.islive, r.rating
FROM company c LEFT JOIN
(SELECT r.*,
ROW_NUMBER() OVER (PARTITION BY r.cid ORDER BY r.thedate DESC) as seqnum
FROM creditrating r
) r
ON c.id = r.cid AND r.seqnum = 1;

Multiple left joins show distinct result with last date

I want to build a discussion board. Therefore I have 3 tables: t_posts, t_boards, t_board_categories. Posts contain Threads (where post_post_id IS NULL) and replies to threads (where post_post_id IS NOT NULL), so it is self-referring. Now I want to show the last 5 posts (Threads and/or Replies) in all boards of all categories. The sql currently looks like this:
SELECT p.post_id,
p.post_board_id,
p.post_user_id,
p2.post_title,
bc.bc_name,
Max(p.post_date) post_date
FROM t_posts p
LEFT JOIN t_posts p2
ON ( p2.post_post_id IS NULL
AND ( p2.post_id = p.post_id
OR p.post_post_id = p2.post_id ) )
LEFT JOIN t_boards b
ON b.board_id = p.post_board_id
LEFT JOIN t_board_categories bc
ON bc.bc_id = b.board_bc_id
WHERE p.post_system_id = '1'
AND p.post_deleted = 0
AND bc.bc_deleted = 0
AND b.board_deleted = 0
GROUP BY p.post_id,
p2.post_id
ORDER BY p2.post_date DESC
LIMIT 5
The result is almost what I want, except of, that multiple replies in one thread will lead to showing only that one thread. What I want is 5 different threads to be shown with the most recent answers, not only one thread 5 times.
I join t_posts p2 for showing the original thread title.
I also tried adding DISTINCT p2.post_id to the SELECT, but it does not change anything.
Schema:
CREATE TABLE `t_board_categories` (
`bc_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`bc_name` varchar(128) COLLATE utf8_unicode_ci DEFAULT '',
`bc_prio` int(11) NOT NULL DEFAULT '0',
`bc_system_id` int(10) unsigned NOT NULL DEFAULT '0',
`bc_deleted` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`bc_id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `t_boards` (
`board_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`board_bc_id` int(10) unsigned DEFAULT NULL,
`board_name` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL,
`board_subtitle` text COLLATE utf8_unicode_ci,
`board_prio` int(11) NOT NULL DEFAULT '0',
`board_system_id` int(10) unsigned NOT NULL DEFAULT '0',
`board_deleted` tinyint(4) NOT NULL DEFAULT '0',
PRIMARY KEY (`board_id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `t_posts` (
`post_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`post_user_id` bigint(20) unsigned DEFAULT NULL,
`post_title` varchar(128) COLLATE utf8_unicode_ci NOT NULL,
`post_text` text COLLATE utf8_unicode_ci NOT NULL,
`post_post_id` bigint(20) unsigned DEFAULT NULL,
`post_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`post_board_id` int(10) unsigned NOT NULL DEFAULT '0',
`post_system_id` int(10) unsigned NOT NULL DEFAULT '0',
`post_deleted` int(2) NOT NULL DEFAULT '0',
PRIMARY KEY (`post_id`)
) ENGINE=InnoDB AUTO_INCREMENT=205 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
INSERT INTO `t_board_categories` (`bc_id`, `bc_name`, `bc_prio`, `bc_system_id`, `bc_deleted`) VALUES (1, 'Test-Category', '1', '1', '0');
INSERT INTO `t_boards` (`board_id`, `board_bc_id`, `board_name`, `board_subtitle`, `board_prio`, `board_system_id`, `board_deleted`) VALUES (1, '1', 'Test-Board', 'Board Subtitle', '1', '1', '0');
INSERT INTO `t_posts` (`post_id`, `post_user_id`, `post_title`, `post_text`, `post_post_id`, `post_date`, `post_board_id`, `post_system_id`, `post_deleted`) VALUES
(1, 14, 'Thread 1', 'Test1', NULL, '2019-05-22 00:18:25', 1, 1, 0),
(2, 14, 'Thread 2', 'Test2', NULL, '2019-05-22 00:18:44', 1, 1, 0),
(3, 14, 'Thread 3', 'Test 3', NULL, '2019-05-22 00:18:51', 1, 1, 0),
(4, 19, 'Thread 4', 'Test 4', NULL, '2019-05-22 00:19:02', 1, 1, 0),
(5, 19, 'Thread 5', 'Test 5', NULL, '2019-05-22 00:19:07', 1, 1, 0),
(6, 19, 'Thread 6', 'Test 6', NULL, '2019-05-22 00:19:15', 1, 1, 0),
(7, 14, 'Reply', 'A', 5, '2019-05-22 00:19:46', 1, 1, 0),
(8, 14, 'Reply', 'B', 5, '2019-05-22 00:19:47', 1, 1, 0),
(9, 14, 'Reply', 'C', 5, '2019-05-22 00:19:49', 1, 1, 0);
Expected Result: One row for thread 1-5 with user-id and date of last reply (userid:14, date: 2019-05-22 00:19:49 for Thread 5, for Thread 1-4 last date is thread-date, userid is thread author userid)
I worked on this the whole evening, would be great to get some help. Thank you in advance!
Your sample data suggests, that post levels cannot span more than two levels (post_post_id cannot be an ID of a post where post_post_id isn't null). Assuming that, you can try to use correlated subqueries getting the sub posts and the post for a post, order them by their date descending and use LIMIT to pick the top one. Also sort the main query by the date of the last sub post descending and use LIMIT to get the top 5. Something along the lines of:
SELECT bc1.bc_id,
bc1.bc_name,
b1.board_id,
b1.board_name,
p1.post_id,
p1.post_title,
(SELECT p2.post_title
FROM t_posts p2
WHERE p1.post_id IN (p2.post_id,
p2.post_post_id)
ORDER BY p2.post_date DESC
LIMIT 1) last_post_title,
(SELECT p2.post_user_id
FROM t_posts p2
WHERE p1.post_id IN (p2.post_id,
p2.post_post_id)
ORDER BY p2.post_date DESC
LIMIT 1) last_post_user_id,
(SELECT p2.post_date
FROM t_posts p2
WHERE p1.post_id IN (p2.post_id,
p2.post_post_id)
ORDER BY p2.post_date DESC
LIMIT 1) last_post_date
FROM t_posts p1
INNER JOIN t_boards b1
ON b1.board_id = p1.post_board_id
INNER JOIN t_board_categories bc1
ON bc1.bc_id = b1.board_bc_id
WHERE p1.post_post_id IS NULL
ORDER BY last_post_date DESC
LIMIT 5;
db<>fiddle

Mysql : Pivot table According to status

My DB structure and details below
CREATE TABLE `tbldakmst` (
`inwardId` int(11) NOT NULL,
`dakType` int(3) DEFAULT NULL,
`dakMarkTo` int(4) DEFAULT NULL,
`letterNo` varchar(100) DEFAULT NULL,
`markDeptt` varchar(20) DEFAULT NULL,
`dakSenderName` varchar(256) DEFAULT NULL,
`subject` varchar(256) DEFAULT NULL,
`remarks` text,
`comments` text,
`handoverDate` datetime DEFAULT NULL,
`handoverTo` int(11) DEFAULT NULL,
`forwardedTo` int(11) DEFAULT NULL,
`forwardedOn` datetime DEFAULT NULL,
`forwardedFrom` int(11) DEFAULT NULL,
`status` enum('0','1','2','3','4','5') DEFAULT NULL COMMENT '0=>CREATED, 1=>MARK TO, 2 => FORWARD TO, 3=>INITIATED, 4=>INITIATED AND DISPOSED, 5=>DISPOSED',
`createdBy` int(11) DEFAULT NULL,
`createdOn` datetime DEFAULT CURRENT_TIMESTAMP,
`modifiedBy` int(11) DEFAULT NULL,
`modifiedOn` datetime DEFAULT NULL,
`fileInitiateBy` int(11) DEFAULT NULL,
`fileInitiatedOn` datetime DEFAULT NULL,
`disposedBy` int(11) DEFAULT NULL,
`disposedOn` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `tbldakmst` (`inwardId`, `dakType`, `dakMarkTo`, `letterNo`, `markDeptt`, `dakSenderName`, `subject`, `remarks`, `comments`, `handoverDate`, `handoverTo`, `forwardedTo`, `forwardedOn`, `forwardedFrom`, `status`, `createdBy`, `createdOn`, `modifiedBy`, `modifiedOn`, `fileInitiateBy`, `fileInitiatedOn`, `disposedBy`, `disposedOn`) VALUES
(1, 0, 3, 'letter 5634', 'Office Dak', 'dheeraj kumar nayak', 'My subject data is here', 'Remrks Datammm VBCBCBBBBB', 'disposed again', '1970-01-26 00:00:00', 3, 3, '2017-05-02 15:14:50', 2, '5', 2, '2017-05-01 17:40:32', 3, '2017-05-07 15:42:40', 3, '2017-05-07 14:07:35', 3, '2017-05-07 14:39:51'),
(2, 0, 4, 'letter no 787887', 'Office Dak', 'kAMLESH kUMAR', 'subj', 'Remarks data', 'MY COMMENTS', '2017-05-02 15:14:50', 4, 2, '2017-05-02 15:14:50', 2, '2', 0, '2017-05-02 11:13:00', 2, '2017-05-05 13:00:44', NULL, NULL, 2, NULL),
(3, 0, 2, 'letter 5634', 'Office Dak', 'dheeraj kumar nayak', 'Need operator credentiasl', 'file putted edited', 'gdfgfg', '1970-01-01 00:00:00', 2, 3, NULL, 2, '1', 2, '2017-05-03 11:03:49', 2, '2017-05-04 14:48:48', NULL, NULL, NULL, NULL),
(4, 0, 2, 'letter 567', 'Office Dak', 'Dheraj Kumar', 'operator activation request from CSC-SPV', 'Personal Visit by EA', 'Disposed Now', '2017-05-07 00:00:00', 2, 2, NULL, 3, '5', 3, '2017-05-07 15:46:06', 2, '2017-05-07 16:10:14', 2, '2017-05-07 16:09:17', 2, '2017-05-07 16:10:14'),
(5, 0, 3, 'letter no 5566rr', 'Office Dak', 'ranjeet vaghle', 'operator request', 'proceed', 'File issues resolved and file is diposed', '0000-00-00 00:00:00', 3, 2, NULL, 3, '4', 3, '2017-05-07 15:55:32', 2, '2017-05-07 16:06:58', 2, '2017-05-07 16:06:58', 2, '2017-05-07 16:06:58'),
(6, 0, 2, 'letter 5634', 'Office Dak', 'dheeraj kumar nayak', 'hjjh', 'hjkhj', NULL, '0000-00-00 00:00:00', 2, NULL, NULL, NULL, '1', 2, '2017-05-07 17:27:36', NULL, NULL, NULL, NULL, NULL, NULL),
(7, 0, 2, 'Letter Number -56788899', 'Office Dak', 'dheeraj kumar nayak', 'dsfs', 'fdsfdsf', 'initiated', '0000-00-00 00:00:00', 2, 2, NULL, 2, '3', 2, '2017-05-07 17:51:56', 2, '2017-05-07 17:52:54', 2, '2017-05-07 17:52:54', NULL, NULL);
ALTER TABLE `tbldakmst`
ADD PRIMARY KEY (`inwardId`);
ALTER TABLE `tbldakmst` MODIFY `inwardId` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=8;
I have tried:
SELECT
sum(CASE
WHEN status = '1' THEN 1
ELSE 0
END) AS 'pending',
sum(CASE
WHEN status = '3' THEN 1
ELSE 0
END) AS 'initiated',
sum(CASE
WHEN status = '4' OR status = '5' THEN 1
ELSE 0
END) AS 'disposed' FROM tbldakmst
Above Query Output Was :
pending initiated disposed
2 1 3
<!-- Note:Status(0,1) ==>Pending ,Status (3) ==>Initiated,Status(4,5)==>Disposed
column FileInitiatedBy => User Value which one has initiated file.
Column disposedBy=> User Value which one has disposed file.
Column dakmarkTo => User Value which one have pending file -->
But I want Result Like this
User | Pending | Initiated | Disposed |
------------------------------------------------------
User 2 | 1 | 1 | 2 |
------------------------------------------------------
User 3 | 2 | 3 | 4 |
------------------------------------------------------
SELECT u.name AS 'Name',
sum(CASE
WHEN tb.status in ('0','1') AND (u.id = tb.dakMarkTo OR u.id = tb.createdBy) THEN 1
ELSE 0
END) AS 'pending' ,
sum(CASE
WHEN tb.status in ('3') AND u.id = tb.fileInitiateBy THEN 1
ELSE 0
END) AS 'initiated',
sum(CASE
WHEN tb.status in ('4', '5') AND u.id = tb.disposedBy THEN 1
ELSE 0
END) AS 'disposed'
FROM
tbldakmst tb, user u
group by u.name

MySQL : quote or no quote implies different result with double

I think I found a MySQL bug. I have a table :
CREATE TABLE `bank` (
`id` int(10) unsigned NOT NULL,
`operation_date` date NOT NULL,
`value_date` date NOT NULL,
`expense` double(10,2) DEFAULT NULL,
`income` double(10,2) DEFAULT NULL,
`label` varchar(255) NOT NULL,
`balance` double(10,2) NOT NULL,
`status` int(1) NOT NULL DEFAULT '0',
`payment_id` int(10) unsigned DEFAULT NULL,
`file_id` int(10) unsigned DEFAULT NULL,
`linked_date` datetime DEFAULT NULL
) ENGINE=InnoDB AUTO_INCREMENT=1590 DEFAULT CHARSET=utf8;
With a few raw of datas
INSERT INTO `bank` (`id`, `operation_date`, `value_date`, `expense`, `income`, `label`, `balance`, `status`, `payment_id`, `file_id`, `linked_date`) VALUES
(260, '2016-10-18', '2016-10-18', 0.00, 1308.95, 'VIR IPSEN PHARMA 1510011184 /INV/00059 18 4 2016', 119099.10, 1, 365, NULL, NULL),
(262, '2016-10-18', '2016-10-18', -1749.60, 0.00, 'VIR DV_AC_CANDRAUD_146_AZERTY', 115599.90, 1, 367, NULL, NULL),
(263, '2016-10-19', '2016-10-19', 0.00, 1920.00, 'VIR SARL FDI 032016292294595200000001 VIR DV-AC-FDAVID-29-UREHAB', 117519.90, 1, 461, NULL, NULL),
(264, '2016-10-19', '2016-10-19', -850.00, 0.00, 'VIR DV_S_ECAMPO_167_4METRIS', 116669.90, 1, 368, NULL, NULL),
(405, '2016-10-18', '2016-10-18', -1749.60, 0.00, 'VIR DV_AC_TSMITH_146_AZERTY', 117349.50, 1, 366, NULL, NULL),
(1305, '2016-08-19', '2016-08-19', -114.00, 0.00, 'PAIEMENT CB 1808 ISLES LES MEL SNCF INTERNET CARTE 13841009', 155074.65, 0, NULL, NULL, NULL),
(1306, '2016-08-22', '2016-08-22', -17.44, 0.00, 'PAIEMENT CB 1908 HELP UBER COM UBER FR AUG19 GR CARTE 13840928', 155057.21, 0, NULL, NULL, NULL),
(1307, '2016-08-22', '2016-08-22', -25.00, 0.00, 'PAIEMENT CB 1908 34933184607 TYPEFORM SL CARTE 13840928', 155032.21, 0, NULL, NULL, NULL),
(1308, '2016-08-22', '2016-08-22', -0.06, 0.00, 'VIR DV_S_SUPERMOTION_31_SAMSHIE', 122504.65, 0, NULL, NULL, NULL);
If I run a query like below (without or without the quote), should the result not be the same? I tested it on 5.5.42 and 5.5.47-0+deb7u1.
mysql> SELECT * FROM `bank` WHERE `expense` = -0.06 ORDER BY `expense` DESC;
+------+----------------+------------+---------+--------+---------------------------------+-----------+--------+------------+---------+-------------+
| id | operation_date | value_date | expense | income | label | balance | status | payment_id | file_id | linked_date |
+------+----------------+------------+---------+--------+---------------------------------+-----------+--------+------------+---------+-------------+
| 1308 | 2016-08-22 | 2016-08-22 | -0.06 | 0.00 | VIR DV_S_SUPERMOTION_31_SAMSHIE | 122504.65 | 0 | NULL | NULL | NULL |
+------+----------------+------------+---------+--------+---------------------------------+-----------+--------+------------+---------+-------------+
1 rows in set (0,00 sec)
mysql> SELECT * FROM `bank` WHERE `expense` = '-0.06' ORDER BY `expense` DESC;
Empty set (0,00 sec)

Mysql self joining on max id returned from first table using groupby

I need a sql that uses self join on max id from first table. Please look at the following image of table. I am grouping the table by service_id but I need the last message of each group. So For service group 5 message count should be 3 and last_message should be thirdMsg5. I wrote a sql below everything else is fine but it is throwing an error in the case of self join. It can't recognize msgTbl1.last_message_id. I think I am calling it before preparing it. I need help to solve this problem what would be the best sql to solve this in one query? And if possible please provide me this query in laravel query builder format.
SELECT count(msgTbl1.id) as message_count,
max(msgTbl1.id) as last_message_id,
msgTbl1.body,
msgTbl2.body as last_message,
services.name as service_name
FROM messages msgTbl1
LEFT JOIN (SELECT id, body FROM messages) AS msgTbl2
ON msgTbl2.id = msgTbl1.last_message_id
LEFT JOIN services on services.id = msgTbl1.service_id
WHERE receiver_id = 4 AND read_user = 'no'
GROUP BY msgTbl1.service_id
sql for the message table
CREATE TABLE `messages` (
`id` int(11) UNSIGNED NOT NULL,
`sender_id` int(11) UNSIGNED DEFAULT NULL,
`receiver_id` int(11) UNSIGNED DEFAULT NULL,
`service_id` int(11) UNSIGNED NOT NULL,
`sender_type` enum('user','agent','admin') NOT NULL,
`receiver_type` enum('user','agent','admin') NOT NULL,
`body` text,
`files` varchar(500) DEFAULT NULL COMMENT 'serialize',
`new_notification` enum('no','yes') NOT NULL DEFAULT 'yes',
`read_user` enum('yes','no') NOT NULL DEFAULT 'no',
`read_agent` enum('yes','no') NOT NULL DEFAULT 'no',
`status` enum('active','archive','deleted') NOT NULL DEFAULT 'active',
`created_at` datetime NOT NULL,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `messages` (`id`, `sender_id`, `receiver_id`, `service_id`, `sender_type`, `receiver_type`, `body`, `files`, `new_notification`, `read_user`, `read_agent`, `status`, `created_at`, `updated_at`) VALUES
(1, 22, 4, 5, 'user', 'agent', 'firstMsg5', NULL, 'yes', 'no', 'yes', 'active', '2016-03-24 00:00:00', '2016-04-12 05:40:28'),
(2, 22, 4, 5, 'user', 'agent', 'secondMsg5', NULL, 'yes', 'no', 'yes', 'active', '2016-03-24 00:00:00', '2016-04-12 05:40:31'),
(3, 22, 4, 9, 'user', 'agent', 'firstMsg9', NULL, 'yes', 'yes', 'yes', 'active', '2016-03-24 00:00:00', '2016-04-12 05:40:45'),
(4, 4, 4, 9, 'agent', 'user', 'secondMsg9', NULL, 'yes', 'yes', 'yes', 'active', '2016-03-24 00:00:00', '2016-04-12 05:40:56'),
(5, 22, 4, 5, 'user', 'agent', 'thirdMsg5', NULL, 'yes', 'yes', 'yes', 'active', '2016-03-24 00:00:00', '2016-04-12 05:41:08');
Try this:
SELECT message_count,
last_message_id,
msgTbl1.body,
services.name as service_name
FROM messages msgTbl1
INNER JOIN (
SELECT MAX(id) AS last_message_id, COUNT(*) AS message_count
FROM messages
WHERE read_user = 'no'
GROUP BY service_id) AS msgTbl2
ON msgTbl1.id = msgTbl2.last_message_id
LEFT JOIN services on services.id = msgTbl1.service_id
WHERE receiver_id = 4