CakePHP Subquery from SQL - mysql

CREATE TABLE IF NOT EXISTS `messages` (
`id` int(11) unsigned NOT NULL auto_increment,
`user_id` int(11) unsigned NOT NULL,
`node_id` int(11) unsigned NOT NULL,
`reciever_id` int(11) unsigned NOT NULL,
`created` datetime default NULL,
`modified` datetime default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ;
INSERT INTO `messages` (`id`, `user_id`, `node_id`, `reciever_id`, `created`, `modified`) VALUES
(1, 1, 1, 15, '2011-12-07 00:00:00', '2011-12-07 02:00:00'),
(2, 15, 1, 1, '2011-12-07 02:00:00', '2011-12-07 02:00:00'),
(3, 15, 2, 1, '2011-12-07 11:00:00', '2011-12-07 11:00:00'),
(4, 1, 2, 15, '2011-12-07 11:00:00', '2011-12-07 11:00:00'),
(5, 1, 3, 18, '2011-12-07 11:00:00', '2011-12-07 11:00:00'),
(6, 18, 3, 1, '2011-12-07 11:00:00', '2011-12-07 11:00:00'),
(7, 1, 4, 18, '2011-12-07 12:00:00', '2011-12-07 12:00:00'),
(8, 18, 4, 1, '2011-12-07 12:00:00', '2011-12-07 12:00:00');
CREATE TABLE IF NOT EXISTS `nodes` (
`id` int(11) unsigned NOT NULL auto_increment,
`message` text NOT NULL,
`author_id` int(11) unsigned NOT NULL,
`read` tinyint(1) default NULL,
`created` datetime default NULL,
`modified` datetime default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;
INSERT INTO `nodes` (`id`, `message`, `author_id`, `read`, `created`, `modified`) VALUES
(1, 'Hi! How are you ? dude wanna meet up this weekend ?', 1, 0, '2011-12-07 02:00:00', '2011-12-07 02:00:00'),
(2, 'Sure. wanna go to Mangalore Pearl to eat Neer Dosa..', 15, 0, '2011-12-07 11:00:00', '2011-12-07 11:00:00'),
(3, 'Hi How are u Buddy ? Long time no see...', 1, 0, '2011-12-07 11:00:00', '2011-12-07 11:00:00'),
(4, 'yeah. are you back in town ? i think we should meet up man. its been ages ....', 18, 0, '2011-12-07 12:00:00', '2011-12-07 12:00:00');
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) unsigned NOT NULL auto_increment,
`first_name` varchar(255) default NULL,
`last_name` varchar(255) default NULL,
`email` varchar(255) default NULL,
`password` varchar(40) default NULL,
`username` varchar(255) default NULL,
`birthday` date default NULL,
`gender` varchar(255) default NULL,
`city_id` int(11) unsigned NOT NULL,
`status` varchar(255) NOT NULL,
`created` datetime default NULL,
`modified` datetime default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=21 ;
I am trying to create a subquery in Cake. but not sure how to start :(
This is the SQL i want to execute
SELECT *
FROM (
SELECT *
FROM messages AS msg
WHERE user_id =1
ORDER BY modified DESC
) AS latest_message
GROUP BY reciever_id
Is it better to use sub Queries or write SQL statement ?

I'm not really sure what the necessity for a subquery is here, wouldn't something like this do the trick?
$this->Message->find('all', array(
'conditions' => array('Message.user_id' => 1),
'order' => array('Message.modified' => 'DESC'),
'group' => array('Message.receiver_id')
));
This would retrieve all the messages from the user with id 1, ordered by date modified and grouped by receiver_id.

Since you are trying to group by the receiver, then why not alter the query to retrieve the receivers and then the messages that belong to each one? Below, I am assuming use of the containable behavior.
$this->Receiver->find('all', array(
'contain' => array(
'Message' => array(
'conditions' => array('Message.user_id' => 1),
'order' => array('Message.modified' => 'DESC'),
)
)
));
EDIT
I added this query to see if it helps based on your comment.
$this->Message->find(
'all',
array(
'conditions' => array('Message.user_id' => 1),
'fields' => array('Message.*', 'MAX(Message.modified) as max_mod'),
'group' => 'Message.receiver_id'
)
);

Related

need a little push with some query details

i have two tables "users" and "bookings"
and i need to count how many users have entered and registered by selected year and every month
and how many amount they have spent for the matched year and month
CREATE TABLE `users` (
`user_id` int(11) NOT NULL,
`user_name` varchar(255) DEFAULT NULL,
`user_nationality` varchar(255) DEFAULT NULL,
`user_birthYear` int(11) DEFAULT NULL,
`user_email` varchar(255) DEFAULT NULL,
`user_passportNumber` varchar(255) DEFAULT NULL,
`user_hotel` varchar(255) DEFAULT NULL,
`gender` varchar(255) NOT NULL,
`addedOn` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `users` (`user_id`, `user_name`, `user_nationality`, `user_birthYear`, `user_email`, `user_passportNumber`, `user_hotel`, `gender`, `addedOn`) VALUES
(104, 'john abraham', 'albania', 1994, 'john#john.com', '11100', 'google', 'male', '2023-01-29 09:06:41'),
(112, 'jah graz', 'morocco', 1990, 'jah#hah.com', '1843', 'df', 'male', '2023-02-06 17:29:58'),
(115, 'ronaldo abraham', 'angola', 1993, 'ronaldo#gmail.com', '87565', 'ng', 'male', '2023-02-06 17:30:42'),
(116, 'zhengjian yangben', 'china', 1983, 'gfjhfghfgh#ytfghj.com', 'e00000000', 'gt', 'female', '2023-02-06 17:30:56'),
(117, 'oksiao tiah', 'china', 1983, 'oksia#ytfghj.com', 'e000000001', 'google', 'female', '2023-02-06 17:31:26');
CREATE TABLE `bookings` (
`booking_id` int(11) NOT NULL,
`user_name` varchar(255) NOT NULL,
`user_birthYear` int(11) NOT NULL,
`user_nationality` varchar(255) NOT NULL,
`user_id` int(11) DEFAULT NULL,
`user_group` varchar(255) NOT NULL,
`place_id` text DEFAULT NULL,
`booked_by` int(11) DEFAULT NULL,
`booked_date` date NOT NULL,
`booked_on` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
`booking_ref` varchar(255) DEFAULT NULL,
`amount` decimal(12,2) NOT NULL,
`status` int(11) DEFAULT NULL,
`isDomestic` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `bookings` (`booking_id`, `user_name`, `user_birthYear`, `user_nationality`, `user_id`, `user_group`, `place_id`, `booked_by`, `booked_date`, `booked_on`, `booking_ref`, `amount`, `status`, `isDomestic`) VALUES
(647, 'john abraham', 1994, 'albania', 104, 'adult', '36', 4, '2023-02-02', '2023-02-02 14:38:42', 'B-12167534871964719944', '200.00', 0, 'false'),
(648, 'zhengjian yangben', 1983, 'china', 116, 'adult', '36', 4, '2023-02-02', '2023-02-02 14:41:12', 'B-83167534874736719834', '300.00', 0, 'false'),
(649, 'zhengjian yangben', 1983, 'china', 104, 'adult', '37', 4, '2023-02-06', '2023-02-03 19:50:43', 'B-41167566360101919834', '100.00', 0, 'false'),
(650, 'john abraham', 1994, 'albania', 104, 'adult', '37', 4, '2023-02-06', '2023-02-06 06:07:03', 'B-41167566360101919834', '0.00', 0, 'false'),
(651, 'john abraham', 1994, 'albania', 116, 'adult', '37', 4, '2023-02-06', '2023-02-06 06:07:44', 'B-54167566365174419944', '0.00', 0, 'false'),
(652, 'zhengjian yangben', 1983, 'china', 116, 'adult', '37', 4, '2023-02-06', '2023-02-06 06:07:44', 'B-54167566365174419944', '0.00', 0, 'false'),
(653, 'john abraham', 1994, 'albania', 104, 'adult', '36', 4, '2023-02-02', '2023-02-02 14:38:42', 'B-12167534871964719944', '200.00', 0, 'false'),
(654, 'john abraham', 1994, 'albania', 104, 'adult', '36', 4, '2023-02-02', '2023-01-01 14:38:42', 'B-12167534871964719944', '200.00', 0, 'false');
here is what i have tried
first:
SELECT
`user_nationality` AS `Nationality`,
COUNT(`user_id`) AS `usersCount`,
MONTHNAME(`addedOn`) AS `monthName`,
MONTH(`addedOn`) AS `month`
FROM `users`
WHERE DATE_FORMAT(`addedOn`,'2023-%m') = DATE_FORMAT(`addedOn`,'2023-%m')
GROUP BY `monthName`,`Nationality`
ORDER BY `month`
from above code i can get the correct results, but i cant get the correct amount if i join bookings table
i need to join bookings table to get total amount for the matched country, year and month
I'm not going to answer specifically, instead, generically to help others. Follow this as a guide and translate this into what you need for your specific use case. But... before I get into the details. You are missing Primary Keys and Foreign Keys from the data model you have provided. Get your basics right.
Looks like you are working with some kind of hotel booking system. Imagine the scenario... you turn up at a hotel in real life, tell the receptionist you have a booking, they ask you your name, and you don't tell them.... You won't be passing reception. You data model is no different. Get the basics right and the rest falls into place.
Anyhow, you need something like this;
SELECT
main_table.id
, SUM(second_table.field_you_want_to_sum)
, MONTH(second_table.created_date)
, YEAR(second_table.created_date)
, CONCAT(YEAR(second_table.created_date), "-", MONTH(second_table.created_Date))
FROM
main_table
LEFT JOIN second_table ON main_table.id = second_table.main_table_id_fk
GROUP BY
main_table.id, CONCAT(YEAR(second_table.created_date), "-", MONTH(second_table.created_date))
;
SUM / COUNT, etc. Same concept in this context. You'll also probably want an ORDER BY in there too, hence why the CONCAT party is erring towards the yyyy-mm-dd format as this is how you need to structure things.
Update

How to pull the last data from table 2 using LEFT JOIN with 2 tables?

I'm coding a chat room using 2 mysql tables. One of these tables is the inbox and the other is the messages table.
I want to find the table "user_mailboxes" from another table belonging to someone else and sort it by grouping advert_id.
I want the last sent message to be at the top and at the specified location. I would be glad if you help.
The SQL code I use:
SELECT *
FROM user_mailboxes
LEFT
JOIN mbox
ON mbox.id = user_mailboxes.message_id
WHERE (user_mailboxes.user = '$users['id']'
AND user_mailboxes.mailbox = 'Out')
|| (user_mailboxes.user = '$users['id']'
AND user_mailboxes.mailbox = 'In')
GROUP
BY user_mailboxes.advert_id
ORDER
BY mbox.created DESC
I'm using a Foreach loop. Result:
user_mailboxes TABLE
mysql
CREATE TABLE `mbox` (
`id` int(100) NOT NULL,
`message` text COLLATE utf8_unicode_ci,
`sentby` int(100) DEFAULT NULL,
`sentto` int(100) DEFAULT NULL,
`created` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `mbox` (`id`, `message`, `sentby`, `sentto`, `created`) VALUES
(1, 'Hello!', 1, 4, '2019-10-25 00:25:38'),
(2, 'Last Messages How are you ?', 1, 4, '2019-10-25 00:26:14'),
(3, 'Welcome', 1, 2, '2019-10-25 00:26:45'),
(4, ':) last messages', 1, 2, '2019-10-25 00:27:02');
mbox TABLE
mysql
CREATE TABLE `user_mailboxes` (
`id` int(100) NOT NULL,
`user` int(100) DEFAULT NULL,
`mailbox` enum('Out','In') COLLATE utf8_unicode_ci DEFAULT NULL,
`message_id` int(100) DEFAULT NULL,
`advert_id` int(100) DEFAULT NULL,
`room_name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `user_mailboxes` (`id`, `user`, `mailbox`, `message_id`, `advert_id`, `room_name`) VALUES
(1, 1, 'Out', 1, 67, '67-1'),
(2, 4, 'In', 1, 67, '67-1'),
(3, 1, 'Out', 2, 67, '67-1'),
(4, 4, 'In', 2, 67, '67-1'),
(5, 1, 'Out', 3, 1, '1-1'),
(6, 2, 'In', 3, 1, '1-1'),
(7, 1, 'Out', 4, 1, '1-1'),
(8, 2, 'In', 4, 1, '1-1');

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 - Selecting rows who's id is not present as a foreign key in another table

In my rails app I have two tables - device_ports and circuits. My goal is to get a list of device_ports whose id is not being used in the physical_port_id column of the circuits table.
I have done something similar before on other tables but here my query only returns one row when it should return 23 rows - there are 24 device ports for this device and one is in use.
select id, name, device_id, multiuse
from device_ports
where (device_id = 6 and multiuse = 1)
or device_ports.id not in (select physical_port_id from circuits)
So this query gets all multiuse ports (so even if the id was referenced in the foreign key, this row should still be returned) and should also get all rows where the device_id is 6 but is not referenced in circuits but only the multiuse row is being returned.
The result from the query is
id | name | device_id | multiuse
------------------------------------
268 | test-1 | 6 | 1
I did try to create an sql fiddle but the build just seems to timeout.
CREATE TABLE `device_ports` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`device_id` int(11) DEFAULT NULL,
`name` tinytext,
`speed` tinytext,
`multiuse` tinyint(1) DEFAULT NULL,
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `id` (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=291 DEFAULT CHARSET=latin1;
INSERT INTO `device_ports` (`id`, `device_id`, `name`, `speed`, `multiuse`, `created_at`, `updated_at`)
*emphasized text*VALUES
(1, 1, 'Test Device Port', '100', 0, NULL, NULL),
(2, 1, 'Test Port 2', '300', 1, NULL, NULL),
(289, 6, 'test-22', '100', 0, NULL, NULL),
(290, 6, 'test-23', '100', 0, NULL, NULL),
(288, 6, 'test-21', '100', 0, NULL, NULL),
(287, 6, 'test-20', '100', 0, NULL, NULL),
(286, 6, 'test-19', '100', 0, NULL, NULL),
(284, 6, 'test-17', '100', 0, NULL, NULL),
(285, 6, 'test-18', '100', 0, NULL, NULL),
(283, 6, 'test-16', '100', 0, NULL, NULL),
(282, 6, 'test-15', '100', 0, NULL, NULL),
(281, 6, 'test-14', '100', 0, NULL, NULL),
(280, 6, 'test-13', '100', 0, NULL, NULL),
(279, 6, 'test-12', '100', 0, NULL, NULL),
(278, 6, 'test-11', '100', 0, NULL, NULL),
(277, 6, 'test-10', '100', 0, NULL, NULL),
(276, 6, 'test-9', '100', 0, NULL, NULL),
(275, 6, 'test-8', '100', 0, NULL, NULL),
(274, 6, 'test-7', '100', 0, NULL, NULL),
(273, 6, 'test-6', '100', 0, NULL, NULL),
(272, 6, 'test-5', '100', 0, NULL, NULL),
(271, 6, 'test-4', '100', 0, NULL, NULL),
(270, 6, 'test-3', '100', 0, NULL, NULL),
(269, 6, 'test-2', '100', 0, NULL, NULL),
(268, 6, 'test-1', '100', 1, NULL, NULL),
(267, 6, 'test-0', '100', 0, NULL, NULL);
CREATE TABLE `circuits` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`organisation_id` int(11) DEFAULT NULL,
`physical_port_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=248 DEFAULT CHARSET=latin1;
INSERT INTO `circuits` (`id`, `organisation_id`, `physical_port_id`)
VALUES (1, 125, 267);
You could try using a LEFT OUTER JOIN:
SELECT DISTINCT d.id, d.name, d.device_id, d.multiuse
FROM device_ports d
LEFT OUTER JOIN circuits c ON c.physical_port_id = d.id
WHERE
(c.physical_port_id IS NULL AND d.device_id = 6)
OR (d.multiuse = 1 AND d.device_id = 6)
ORDER BY d.id
There are several techniques for this query, take a look at What's the difference between NOT EXISTS vs. NOT IN vs. LEFT JOIN WHERE IS NULL?.
SELECT p.*
FROM device_ports p
LEFT
JOIN circuits c
ON c.physical_port_id = p.id
WHERE p.device_id = 6
AND multiuse = 1
AND c.id IS NULL;

SQLBuddy: How to select database?

I have the following sql which I want to import with SQLBuddy.
However I get an error telling that no database selected.
Could anyone tell me what line I need to add please?
CREATE TABLE IF NOT EXISTS `jos_banner` (
`bid` int(11) NOT NULL AUTO_INCREMENT,
`cid` int(11) NOT NULL DEFAULT '0',
`type` varchar(30) NOT NULL DEFAULT 'banner',
`name` varchar(255) NOT NULL DEFAULT '',
`alias` varchar(255) NOT NULL DEFAULT '',
`imptotal` int(11) NOT NULL DEFAULT '0',
`impmade` int(11) NOT NULL DEFAULT '0',
`...
...
...
PRIMARY KEY (`bid`),
KEY `viewbanner` (`showBanner`),
KEY `idx_banner_catid` (`catid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=12 ;
--
-- Dumping data for table `jos_banner`
--
INSERT INTO `jos_banner` (`bid`, `cid`, `type`, `name`, `alias`, `imptotal`, `impmade`, `clicks`, `imageurl`, `clickurl`, `date`, `showBanner`, `checked_out`, `checked_out_time`, `editor`, `custombannercode`, `catid`, `description`, `sticky`, `ordering`, `publish_up`, `publish_down`, `tags`, `params`) VALUES
(1, 1, 'banner', 'OSM 1', 'osm-1', 0, 47, 0, 'osmbanner1.png', 'http://www.opensourcematters.org', '2004-07-07 15:31:29', 0, 0, '0000-00-00 00:00:00', '', '', 13, '', 0, 1, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '', ''),
(2, 1, 'banner', 'OSM 2', 'osm-2', 0, 49, 0, 'osmbanner2.png', 'http://www.opensourcematters.org', '2004-07-07 15:31:29', 0, 0, '0000-00-00 00:00:00', '', '', 13, '', 0, 2, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '', ''),
(3, 2, '', 'Joomla!', 'joomla', 0, 1363, 0, '', 'http://www.joomla.org', '2009-05-29 ...
...
...
In the SQLBuddy homepage you need to create a database first, name it as whatever you want and then from the left sidebar select your new created database, then from the top menu select Query, paste your sql and go on!
use databasename;
Like it says: select a database.
Say your database is called ShinsBlog, add this to the start of your code:
use ShinsBlog;