how to join Between four tables on mysql - mysql

i have 4 tables for mysql database, how i join Between them
users:
userid|username
1 | mark
2 | jon
awards_user :
awardid|userid
1 |1
2 |2
cat :
catid|catname
1 | english
2 | computer
awards :
awardid|catid|awardname|awardlink
1 |1 |best1 |pic link
2 |2 |best2 |pic link
resulte :
userid|username|catid|catname|awardid|awardname|awardlink
okay , that is my try :
works but Shows only one result, when there is a member holds a award
، I want to show all the awards, even if there is no one holds them .
$all_awards = $db->query_read(" SELECT * FROM " . TABLE_PREFIX . " users,awards_user,cat,awards
WHERE
awards_user.awardid = awards.awardid
AND
awards_user.userid = users.userid
AND
awards.catid = cat.catid
");
CREATE TABLE `awards` (
`id` int(10) unsigned NOT NULL auto_increment,
`forumid` int(10) unsigned NOT NULL,
`name` varchar(100) NOT NULL default '',
`link` varchar(100) NOT NULL default '',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
--
-- Dumping data for table `awards`
--
INSERT INTO `awards` VALUES (1, 2, 'award one', 'http://www.mwadah.com/pict/noway9.gif');
INSERT INTO `awards` VALUES (2, 1, 'award 2', 'http://www.forum-ksa.com/up/uploads/images/forum-ksac59a7122d1.gif');
-- --------------------------------------------------------
--
-- Table structure for table `awards_user`
--
CREATE TABLE `awards_user` (
`id` int(10) unsigned NOT NULL auto_increment,
`awardid` int(10) unsigned NOT NULL,
`userid` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;
--
-- Dumping data for table `awards_user`
--
INSERT INTO `awards_user` VALUES (2, 2, 2);
-- --------------------------------------------------------
--
-- Table structure for table `forum`
--
CREATE TABLE `forum` (
`forumid` smallint(5) unsigned NOT NULL auto_increment,
`title` varchar(100) NOT NULL default '',
PRIMARY KEY (`forumid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=2;
--
-- Dumping data for table `forum`
--
INSERT INTO `forum` VALUES (1,'Main Category');
INSERT INTO `forum` VALUES (2,'Main Forum');
-- --------------------------------------------------------
--
-- Table structure for table `user`
--
CREATE TABLE `user` (
`userid` int(10) unsigned NOT NULL auto_increment,
`username` varchar(100) NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;
--
-- Dumping data for table `user`
--
INSERT INTO `user` VALUES (1,'admin');
INSERT INTO `user` VALUES (1,'mark');

You could structure your JOIN query like this:
SELECT *
FROM users
JOIN awards_user USING(userid)
JOIN awards USING(awardid)
JOIN cat USING(catid)
Then you can add a WHERE clause to filter the result.

SELECT awards.userid,
username,
awards.catid,
catname,
awards.awardid,
awardname,
awardlink
FROM users,
awards_user,
cat,
awards
WHERE awards_user.userid = users.userid
AND awards_user.awardid = awards.awardid
AND cat.catid = awards.catid;

Related

Why delete query only delete one record

Hi I’ve got the folowing query:
DELETE tickets, archive, files
FROM tickets
LEFT JOIN ticket_files
ON ticket_files.ticket_id = tickets.ticket_id
LEFT JOIN archive
ON archive.document_id = ticket_files.document_id
LEFT JOIN files
ON files.file_id = ticket_files.file_id
WHERE tickets.ticket_id = 21
When the ticket doesn’t have any record in the junction table ticket_files then the ticket is deleted correctly but if there is more than one record in the ticket_files then only one record is deleted from the tables archive and files. How can i make sure all the joined records are deleted also from archive and files? many thanks
This is the database structure. As you can see the ticket with ID 1 has got two files associated in the ticket_files table but ticket with ID 2 doesn't have any files associated.
-- phpMyAdmin SQL Dump
-- version 5.1.0
-- https://www.phpmyadmin.net/
--
-- Host: localhost:8889
-- Generation Time: Mar 28, 2022 at 07:35 PM
-- Server version: 5.7.34
-- PHP Version: 8.0.8
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
--
-- Database: `test`
--
-- --------------------------------------------------------
--
-- Table structure for table `archive`
--
CREATE TABLE `archive` (
`document_id` int(11) NOT NULL,
`document_sent_by` int(11) NOT NULL,
`document_description` varchar(255) NOT NULL,
`document_category` int(11) NOT NULL,
`document_status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1=public 0=draft',
`document_featured` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0=no 1=yes',
`document_note` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `archive`
--
INSERT INTO `archive` (`document_id`, `document_sent_by`, `document_description`, `document_category`, `document_status`, `document_featured`, `document_note`) VALUES
(23, 1, 'File one', 7, 1, 0, 'File one'),
(24, 1, 'File two', 7, 1, 0, 'File two');
-- --------------------------------------------------------
--
-- Table structure for table `files`
--
CREATE TABLE `files` (
`file_id` int(11) NOT NULL,
`file_name` varchar(255) NOT NULL,
`file_type` varchar(255) NOT NULL,
`file_size` varchar(255) NOT NULL,
`file_date` datetime DEFAULT CURRENT_TIMESTAMP,
`file_category` int(11) NOT NULL,
`file_status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1=public 0=draft',
`file_path` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `files`
--
INSERT INTO `files` (`file_id`, `file_name`, `file_type`, `file_size`, `file_date`, `file_category`, `file_status`, `file_path`) VALUES
(23, '1648496062', 'application/pdf', '9514', '2022-03-02 00:00:00', 7, 1, '/docs/1648496062.pdf'),
(24, '1648496079', 'application/pdf', '146367', '2022-03-09 00:00:00', 7, 1, '/docs/1648496079.pdf');
-- --------------------------------------------------------
--
-- Table structure for table `tickets`
--
CREATE TABLE `tickets` (
`ticket_id` int(11) NOT NULL,
`ticket_sent_by` int(11) NOT NULL,
`building_id` int(11) NOT NULL,
`ticket_subject` varchar(255) NOT NULL,
`ticket_object` text NOT NULL,
`ticket_priority` tinyint(1) NOT NULL,
`ticket_status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1=aperto 2=lavorazione 3=chiuso',
`ticket_comments` tinyint(1) NOT NULL DEFAULT '1' COMMENT '0=no 1=yes',
`ticket_visibility` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1=public 0=draft',
`ticket_featured` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0=no 1=yes',
`ticket_private` tinyint(1) NOT NULL DEFAULT '0' COMMENT ' 0=no 1=yes ',
`ticket_open_time` datetime DEFAULT CURRENT_TIMESTAMP,
`ticket_edit_time` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `tickets`
--
INSERT INTO `tickets` (`ticket_id`, `ticket_sent_by`, `building_id`, `ticket_subject`, `ticket_object`, `ticket_priority`, `ticket_status`, `ticket_comments`, `ticket_visibility`, `ticket_featured`, `ticket_private`, `ticket_open_time`, `ticket_edit_time`) VALUES
(1, 1, 13, 'Ticket with files', '<p>this ticket has files<br /></p>', 1, 1, 0, 1, 0, 0, '2022-03-28 20:33:59', NULL),
(2, 1, 13, 'Ticket with no files', '<p>ticket with no files<br /></p>', 1, 1, 0, 1, 0, 0, '2022-03-28 20:35:02', NULL);
-- --------------------------------------------------------
--
-- Table structure for table `ticket_files`
--
CREATE TABLE `ticket_files` (
`ticket_id` int(11) NOT NULL,
`document_id` int(11) NOT NULL,
`file_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `ticket_files`
--
INSERT INTO `ticket_files` (`ticket_id`, `document_id`, `file_id`) VALUES
(1, 23, 23),
(1, 24, 24);
--
-- Indexes for dumped tables
--
--
-- Indexes for table `archive`
--
ALTER TABLE `archive`
ADD PRIMARY KEY (`document_id`);
--
-- Indexes for table `files`
--
ALTER TABLE `files`
ADD PRIMARY KEY (`file_id`);
--
-- Indexes for table `tickets`
--
ALTER TABLE `tickets`
ADD PRIMARY KEY (`ticket_id`);
--
-- Indexes for table `ticket_files`
--
ALTER TABLE `ticket_files`
ADD KEY `ticket_id` (`ticket_id`),
ADD KEY `document_id` (`document_id`) USING BTREE,
ADD KEY `file_id` (`file_id`);
-- AUTO_INCREMENT for table `archive`
--
ALTER TABLE `archive`
MODIFY `document_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=25;
--
-- AUTO_INCREMENT for table `files`
--
ALTER TABLE `files`
MODIFY `file_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=25;
--
-- AUTO_INCREMENT for table `tickets`
--
ALTER TABLE `tickets`
MODIFY `ticket_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;
--
-- Constraints for table `ticket_files`
--
ALTER TABLE `ticket_files`
ADD CONSTRAINT `ticket_files_ibfk_1` FOREIGN KEY (`ticket_id`) REFERENCES `tickets` (`ticket_id`) ON DELETE CASCADE,
ADD CONSTRAINT `ticket_files_ibfk_2` FOREIGN KEY (`document_id`) REFERENCES `archive` (`document_id`) ON DELETE CASCADE,
ADD CONSTRAINT `ticket_files_ibfk_3` FOREIGN KEY (`file_id`) REFERENCES `files` (`file_id`) ON DELETE CASCADE;
COMMIT;
We can add ticket_files to the list of the tables in the DELETE:
select * from ticket_files;
ticket_id | document_id | file_id
--------: | ----------: | ------:
1 | 23 | 23
1 | 24 | 24
DELETE tickets, archive, files, ticket_files
FROM tickets
LEFT JOIN ticket_files
ON ticket_files.ticket_id = tickets.ticket_id
LEFT JOIN archive
ON archive.document_id = ticket_files.document_id
LEFT JOIN files
ON files.file_id = ticket_files.file_id
WHERE tickets.ticket_id = 1
✓
select * from ticket_files;
ticket_id | document_id | file_id
--------: | ----------: | ------:
db<>fiddle here

How to count correctly 2 inner levels count?

I have a structure for a university DB wherein I have three tables: room, students, possessions
CREATE TABLE `rooms` (
`id` INT(10) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL COLLATE 'utf8_general_ci',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `name` (`name`) USING BTREE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=3
;
CREATE TABLE `students` (
`id` INT(10) NOT NULL AUTO_INCREMENT,
`ref_room_id` INT(10) NULL DEFAULT NULL,
`student_name` VARCHAR(50) NOT NULL COLLATE 'utf8_general_ci',
PRIMARY KEY (`id`) USING BTREE,
INDEX `FK_students_room` (`ref_room_id`) USING BTREE,
CONSTRAINT `FK_students_room` FOREIGN KEY (`ref_room_id`) REFERENCES `university`.`rooms` (`id`) ON UPDATE CASCADE ON DELETE SET NULL
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=6
;
CREATE TABLE `possessions` (
`id` INT(10) NOT NULL AUTO_INCREMENT,
`ref_student_id` INT(10) NOT NULL,
`name` VARCHAR(50) NOT NULL DEFAULT '' COLLATE 'utf8_general_ci',
PRIMARY KEY (`id`) USING BTREE,
INDEX `FK__students` (`ref_student_id`) USING BTREE,
CONSTRAINT `FK__students` FOREIGN KEY (`ref_student_id`) REFERENCES `university`.`students` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=4
;
INSERT INTO rooms (name) VALUES ('a'),('b');
INSERT INTO students (`ref_room_id`, `student_name`) VALUES
(3,1),
(3,2),
(3,3),
(3,4);
INSERT INTO possessions (ref_student_id, name) VALUES
(7,'a')
(7,'aa'),
(7,'aaa'),
(8,'aaaa'),
(9,'aaaaa'),
(6,'aaaaaa'),
(7,'aaaaaaa');
So, in order to present such a table in MySQL, I created the procedure
CREATE DEFINER=`root`#`localhost` PROCEDURE `get_data`()
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
SELECT r.id AS room_id, r.name, COUNT(s.id) AS student_num, COUNT(p.id) AS possessions_num
FROM rooms r
INNER JOIN students s ON s.ref_room_id = r.id
INNER JOIN possessions p ON p.ref_student_id = s.id
GROUP BY r.name;
END
but what I get is
First of all, it misses the room and secondly instead of 4 students it shows 7...
What am I doing wrong?
Consider the following (and note that my data set may vary slightly from yours...)
DROP TABLE IF EXISTS rooms;
CREATE TABLE `rooms` (
`id` INT(10) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL ,
PRIMARY KEY (`id`)
);
DROP TABLE IF EXISTS students;
CREATE TABLE `students` (
`id` INT(10) NOT NULL AUTO_INCREMENT,
`ref_room_id` INT(10) NULL DEFAULT NULL,
`student_name` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`)
);
DROP TABLE IF EXISTS possessions;
CREATE TABLE `possessions` (
`id` INT NOT NULL AUTO_INCREMENT,
`ref_student_id` INT NOT NULL,
`name` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO rooms VALUES (1,'a'),(2,'b');
INSERT INTO students VALUES
(11,1,1),
(12,1,2),
(13,1,3),
(14,1,4);
INSERT INTO possessions VALUES
(101,11,'apple'),
(102,11,'banana'),
(103,11,'cherry'),
(104,12,'date'),
(105,15,'elderberry'),
(106,13,'fig'),
(107,14,'huckleberry');
SELECT r.*
, COUNT(DISTINCT s.id) total_students
, COUNT(DISTINCT p.id) total_possessions
FROM rooms r
JOIN students s
ON s.ref_room_id = r.id
JOIN possessions p
ON p.ref_student_id = s.id
GROUP
BY r.id;
+----+------+----------------+-------------------+
| id | name | total_students | total_possessions |
+----+------+----------------+-------------------+
| 1 | a | 4 | 6 |
+----+------+----------------+-------------------+
Or...
SELECT r.*
, COUNT(DISTINCT s.id) total_students
, COUNT(DISTINCT p.id) total_possessions
FROM rooms r
LEFT
JOIN students s
ON s.ref_room_id = r.id
LEFT
JOIN possessions p
ON p.ref_student_id = s.id
GROUP
BY r.id;
+----+------+----------------+-------------------+
| id | name | total_students | total_possessions |
+----+------+----------------+-------------------+
| 1 | a | 4 | 6 |
| 2 | b | 0 | 0 |
+----+------+----------------+-------------------+

Multiple Joins With Condition

I have the following schema
CREATE TABLE IF NOT EXISTS `params` (
`id` int(6) unsigned NOT NULL,
`parameter` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `entry` (
`id` int(6) unsigned NOT NULL,
`param_id` int(6) unsigned NOT NULL,
`value` int(6) unsigned NOT NULL,
`access_id` int(6) unsigned NOT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `enabled` (
`id` int(6) unsigned NOT NULL,
`param_id` int(6) unsigned NOT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
INSERT INTO `params` (`id`, `parameter`) VALUES
('1','Height'),
('2', 'Weight'),
('3', 'Texture'),
('4', 'Colour');
INSERT INTO `entry` (`id`, `param_id`,`value`,`access_id`) VALUES
('1','1','5.2','1'),
('2','2','80','2'),
('3','1','6','2');
INSERT INTO `enabled` (`id`, `param_id`) VALUES
('1','1'),('2','2');
I am trying to get all parameter values with access_id of 1 from the entry table
OR
All Parameters that are enabled which (DOES NOT exist in the entry table with access_idof 1)
So the output should be
id parameter value access_id
1 Height 5 1
2 Weight NULL NULL
The second entry here has a value of null because although it is enabled it does not have an access_id of 1 in the entry table
The schema here http://sqlfiddle.com/#!9/103016
select p.*, e.value, e.access_id from params p
inner join entry e on p.id= e.param_id and e.access_id = 1
union
select p.*, null,null from params p
inner join enabled enb on p.id=enb.param_id
where enb.param_id not in (select param_id from entry where access_id = 1)

how to count same rating from field in sql

I have a problem counting ratings in SQL. This is what my data looks like:
data
CREATE TABLE `restaurant` (
`id_restaurant` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id_restaurant`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
insert into `restaurant`(`id_restaurant`,`name`) values (1,'Mc Donald');
insert into `restaurant`(`id_restaurant`,`name`) values (2,'KFC');
CREATE TABLE `user` (
`id_user` int(11) NOT NULL AUTO_INCREMENT,
`userName` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id_user`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
insert into `user`(`id_user`,`userName`) values (1,'Audey');
CREATE TABLE `factors` (
`factor_id` int(11) NOT NULL AUTO_INCREMENT,
`factor_clean` int(11) NOT NULL DEFAULT '0',
`factor_delicious` int(11) NOT NULL DEFAULT '0',
`id_restaurant` int(11) DEFAULT NULL,
`id_user` int(11) DEFAULT NULL,
PRIMARY KEY (`factor_id`),
KEY `id_restaurant` (`id_restaurant`),
KEY `id_user` (`id_user`),
CONSTRAINT `factors_ibfk_1` FOREIGN KEY (`id_restaurant`) REFERENCES `restaurant` (`id_restaurant`),
CONSTRAINT `factors_ibfk_2` FOREIGN KEY (`id_user`) REFERENCES `user` (`id_user`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
insert into `factors`(`factor_id`,`factor_clean`,`factor_delicious`,`id_restaurant`,`id_user`) values (1,1,5,1,1);
insert into `factors`(`factor_id`,`factor_clean`,`factor_delicious`,`id_restaurant`,`id_user`) values (2,0,5,1,1);
insert into `factors`(`factor_id`,`factor_clean`,`factor_delicious`,`id_restaurant`,`id_user`) values (3,1,5,1,1);
insert into `factors`(`factor_id`,`factor_clean`,`factor_delicious`,`id_restaurant`,`id_user`) values (4,3,3,1,1);
And the result should be like this, Show all ratings (1,2,3,4,5) and their count from the fields rating_clean, rating_delicious, and rating_clean
Thanks for your help.
but the result i get
SELECT COUNT(`factor_clean`+`factor_delicious`),'1' AS rating_1 FROM `factors` WHERE 1 GROUP BY `id_restaurant`
result not should like this
the result should not like that,
my question is, how to select just factor_clean and factor_delicious where factor_clean =1 and factor_delicious = 1
Use union all to unpivot the data and then aggregate:
select id_restaurant, rating, count(*)
from ((select r.id_restaurant, r.rating_clean as rating, r.date
from ratings r
) union all
(select r.id_restaurant, r.rating_delicious, r.date
from ratings r
) union all
(select r.id_restaurant, r.rating_clean2, r.date
from ratings r
)
) r
group by id_restaurant, rating
order by id_restaurant, rating;
For example this is solution for table with colums rating_delicious and rating_clean (only one!):
First of all you should create additional table, I called it factors:
CREATE TABLE `factors` (
`factor_id` int(11) NOT NULL AUTO_INCREMENT,
`factor_clean` int(11) NOT NULL DEFAULT '0',
`factor_delicious` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`factor_id`)
)
Next add two records:
INSERT INTO `factors` (`factor_id`, `factor_clean`, `factor_delicious`) VALUES (NULL, '1', '0'), (NULL, '0', '1');
Now you can join this tables and get results:
SELECT x.id_restaurant
, (x.rating_clean * f.factor_clean) + (x.rating_delicious * f.factor_delicious) AS rating
, count(*)
FROM your_table x
JOIN factors f
WHERE 1
GROUP
BY x.id_restaurant
, rating
In order to use next colum (rating_third), you should and column factor_third to factors, insert new row with 1 in this column and finally add something like your_table.rating_third*factors.factor_third to sum in SELECT

Update row after insert from a another table

I use MySql and have two tables, master and inventory. Now I need a trigger after insert update inventory table field product_description from master table field product_description.
Example:
master table:
pmid - product_name - product_description - price
1 tv HD tv 10
inventory table:
invid - pmid - product_description - color
1 1 black
Trigger should insert product_description from partmaster where pmid = pmid.
CREATE TABLE IF NOT EXISTS `master` (
`pmid` int(11) NOT NULL AUTO_INCREMENT,
`product_name` varchar(255) NOT NULL,
`product_description` varchar(255) NOT NULL,
`price` varchar(10) NOT NULL,
PRIMARY KEY (`pmid`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=20 ;
CREATE TABLE IF NOT EXISTS `inventory` (
`invid` int(11) NOT NULL AUTO_INCREMENT,
`pmid` int(11) NOT NULL,
`product_description` varchar(255) NOT NULL,
`color` int(11) NOT NULL,
PRIMARY KEY (`invid`),
KEY `pmid` (`pmid`), //foreign key master table//
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=20 ;
Thanks
delimiter //
CREATE TRIGGER update_inventory AFTER INSERT ON master
FOR EACH ROW
BEGIN
UPDATE inventory I SET I.product_description = new.product_description
WHERE (I.pmid = new.pmid );
END; //
delimiter ;
I find your data inconsistent:
1. How can you have pmid in inventory without having it in master table?
2. Color field is numeric; contradicts your example.