MySql. 'group by' by parts - mysql

there is a table
CREATE TABLE geography_schedule (
id int(10) UNSIGNED NOT NULL,
geography_address_id int(10) UNSIGNED NOT NULL,
geography_city_id int(10) UNSIGNED NOT NULL,
sort int(5) UNSIGNED NOT NULL DEFAULT '500',
site varchar(5) NOT NULL DEFAULT 'site',
group_id int(10) NOT NULL DEFAULT '0',
day int(10) NOT NULL DEFAULT '1',
all_day tinyint(2) NOT NULL DEFAULT '0',
freeday int(10) NOT NULL DEFAULT '0',
from varchar(5) NOT NULL DEFAULT '09:00',
to varchar(5) NOT NULL DEFAULT '18:00',
timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
timestamp_update timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO geography_schedule (from, to, geography_address_id, day_from, day_to, group_id) VALUES
('09:00', '18:00', 533, 1, 1, 1),
('09:00', '18:00', 533, 2, 2, 1),
('11:00', '17:00', 533, 3, 3, 1),
('11:00', '17:00', 533, 4, 4, 1),
('09:00', '18:00', 533, 5, 5, 1),
('10:00', '17:00', 533, 6, 6, 1),
('09:00', '18:00', 533, 7, 7, 1);
I have a mysql query from this table enter image description here
SELECT `from`,`to`, `geography_address_id`, MIN(`day`) as `day_from`
,MAX(`day`) as `day_to`,`group_id`
FROM `geography_schedule`
WHERE `geography_address_id` = 533
GROUP BY `from`,`to`
ORDER BY `geography_schedule`.`day` ASC
result:
I need to group by lines 9:00 - 18:00 to save days day_from & day_to in proper order.
Is it possible to use GROUP BY in such a way it will give the result like this?

Related

Sort soccer/football leaderboard table with direct matches

I'm going crazy to get a sorted leaderbord for my project. I need a help because I have to sort the table by points, goal difference and direct matches. My problem is direct matches.
MySQL version: 5.7.29
Here the tables structures and some example data:
CREATE TABLE `matches` (
`id` bigint(20) UNSIGNED NOT NULL,
`club_id_home` bigint(20) UNSIGNED NOT NULL,
`goals_home` tinyint(3) UNSIGNED NOT NULL DEFAULT '0',
`club_id_away` bigint(20) UNSIGNED NOT NULL,
`goals_away` tinyint(3) UNSIGNED NOT NULL DEFAULT '0',
`competition_id` bigint(20) UNSIGNED DEFAULT NULL,
`round` smallint(5) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `matches` (`id`, `club_id_home`, `goals_home`, `club_id_away`, `goals_away`, `competition_id`, `round`) VALUES
(1, 1, 3, 2, 2, 1, 1),
(2, 3, 0, 4, 0, 1, 1),
(3, 3, 1, 1, 1, 1, 1),
(4, 4, 1, 2, 0, 1, 1);
CREATE TABLE `leaderboards` (
`id` bigint(20) UNSIGNED NOT NULL,
`club_id` bigint(20) UNSIGNED NOT NULL,
`competition_id` bigint(20) UNSIGNED DEFAULT NULL,
`points` tinyint(3) UNSIGNED NOT NULL,
`wins` tinyint(3) UNSIGNED NOT NULL,
`losses` tinyint(3) UNSIGNED NOT NULL,
`draws` tinyint(3) UNSIGNED NOT NULL,
`goals_for` tinyint(3) UNSIGNED NOT NULL,
`goals_against` tinyint(3) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `leaderboards` (`id`, `club_id`, `competition_id`, `points`, `wins`, `losses`, `draws`, `goals_for`, `goals_against`) VALUES
(1, 1, 1, 4, 1, 1, 0, 4, 3),
(2, 2, 1, 0, 0, 0, 2, 2, 4),
(3, 3, 1, 2, 0, 2, 0, 1, 1),
(4, 4, 1, 4, 1, 1, 0, 1, 0);
So I have to check points (easy) and goal difference (easy) from leaderboards table, and direct matches from matches table so that if Club A and Club B have same points I have to check if Club A won or lost (or tied) against Club B.
So in my example I would like to see a leaderboard sorted like this:
club_id 4 | points: 4 | goals difference: 1
club_id 1 | points: 4 | goals difference: 1
club_id 3 | points: 2 | goals difference: 0
club_id 2 | points: 0 | goals difference: -2
Club 4 is first because it won the direct match against club 1.
How can I do it? Is it possible?
Thank you in advance!

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

Query was working in MYSQL but not MYSQLI

My query was working in MYSQL but not in MYSQLI.
I'm selecting students that have done the pre AND post test.
SELECT
studid as Username,
prepoints as 'Fitness Assessment Points Grade',
end AS 'End-of-Line Indicator'
FROM
fittest, points
WHERE
YEAR(submitted) = '2017'
AND semester = 'summer2'
GROUP BY studid
HAVING
(MAX(prepost = 'pre' ) + MAX(prepost = 'post')) = 2 AND COUNT(DISTINCT prepost) = 2
Any ideas what changes need to be made to get it working again?
Here is some sample data:
CREATE TABLE `fittest` ( `id` int(11) NOT NULL, `submitted`
datetime DEFAULT NULL, `studid` varchar(100) DEFAULT NULL,
`semester` varchar(50) DEFAULT NULL, `instructor` varchar(30)
DEFAULT NULL, `course` enum('PHED 1164') DEFAULT NULL, `section`
enum('5001','5003','5005','5007','5009','5011','5013','5015','5017','5019','5021','5023','5025','5027','5029','5031','5033','5035','5037','5039','5041','5043','5045','5047','5049','5051','5053','5055','5057','5059','5061','5063','5065','5067','5069')
DEFAULT NULL, `age` varchar(50) DEFAULT NULL, `gender`
enum('m','f') DEFAULT NULL, `ethnicity` enum('Hispanic','African
American','Asian','White-Non Hispanic','Other') DEFAULT NULL,
`height` char(4) DEFAULT NULL, `weight` int(3) DEFAULT NULL,
`flexibility` int(2) DEFAULT NULL, `crunches` int(3) DEFAULT NULL,
`pushups` int(3) DEFAULT NULL, `treadtimemin` int(2) DEFAULT NULL,
`treadtimesec` int(2) NOT NULL, `treadhr` int(3) DEFAULT NULL,
`prepost` enum('pre','post') NOT NULL, `end` char(1) NOT NULL
DEFAULT '#' ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `fittest` (`id`, `submitted`, `studid`, `semester`,
`instructor`, `course`, `section`, `age`, `gender`, `ethnicity`,
`height`, `weight`, `flexibility`, `crunches`, `pushups`,
`treadtimemin`, `treadtimesec`, `treadhr`, `prepost`, `end`) VALUES
(17, '2017-01-02 21:55:33', 'slacker', 'spring', 'Tim', 'PHED 1164',
'5001', '32', 'm', NULL, '69.5', 155, NULL, 29, 34, 22, 15, 76, 'pre',
'#'), (16, '2017-01-02 21:31:34', 'bfun', 'spring', 'Tim', 'PHED
1164', '5001', '32', 'm', NULL, '69.5', 122, NULL, 37, 36, 18, 14, 76,
'post', '#'), (15, '2017-01-02 21:31:09', 'bfun', 'spring', 'Tim',
'PHED 1164', '5001', '32', 'm', NULL, '69.5', 129, NULL, 21, 20, 23,
14, 76, 'pre', '#'),
I just figured out the issue isn't with the query. It was with the input. All the input had post for the prepost value so there were no results that were showing. Thanks for your help.

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

Multiple Condition from 2 columns with different criteria

Need to Select rows from table where need to use 2 columns with different criteria
CREATE TABLE IF NOT EXISTS `spec_property` (
`sp_id` int(11) unsigned NOT NULL,
`spm_id` int(11) unsigned NOT NULL,
`spec_value` varchar(255) NOT NULL,
`spec_last_value` varchar(55) DEFAULT NULL,
`product_id` int(11) unsigned NOT NULL,
`spec_order_by` tinyint(2) unsigned DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=77 ;
ALTER TABLE `spec_property`
ADD PRIMARY KEY (`sp_id`), ADD KEY `product_id` (`product_id`), ADD KEY `spec_value` (`spec_value`);
ALTER TABLE `spec_property`
MODIFY `sp_id` int(11) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=75;
INSERT INTO `spec_property` (`sp_id`, `spm_id`, `spec_value`, `spec_last_value`, `product_id`, `spec_order_by`) VALUES
(31, 23, 'Octa Core', NULL, 4, NULL),
(34, 26, '2048', 'MB', 4, NULL),
(35, 27, '8192', 'MB', 4, NULL),
(36, 28, '2048', 'MB', 4, NULL),
(69, 62, 'Android', NULL, 4, NULL),
(70, 63, '5', NULL, 4, NULL),
(71, 65, 'Yes', NULL, 4, NULL),
(72, 66, 'Yes', NULL, 4, NULL),
(73, 67, '32000', NULL, 4, NULL),
(74, 68, '25', 'fps', 4, NULL);
http://sqlfiddle.com/#!9/95329/13
SELECT distinct(product_id)
FROM `spec_property`
WHERE (spm_id = '62' AND spec_value IN ('Android' , 'Windows'))
AND (spm_id = '27' AND spec_value BETWEEN 4096 AND 131072 )
If I use the 'OR' condition I can get this result:
( http://sqlfiddle.com/#!9/95329/1 ). Actually i need to find product id's which are matches the filter options like
SELECT DISTINCT (product_id)
FROM spec_property
WHERE spm_id_62 IN ('Android', 'Windows')
AND spm_id_27 BETWEEN 4096 AND 131072
AND spm_id_26 BETWEEN 4096 AND 131072
You could try another set of parenthesis to structure the query
SELECT distinct(product_id)
FROM `spec_property`
WHERE ((spm_id = '62' AND spec_value IN ('Android' , 'Windows'))
OR (spm_id = '27' AND spec_value BETWEEN 4096 AND 131072 )
OR (spm_id = '26' AND spec_value BETWEEN 4096 AND 131072 ))