mysql consult in same table - mysql

i have this table
INSERT INTO `relationships` (`id`, `term_id`, `order`) VALUES
(1, 1, 0),
(4, 2, 0),
(4, 3, 0),
(4, 4, 0),
(4, 5, 0),
(4, 7, 0),
(4, 8, 0),
(6, 3, 0),
(6, 8, 0),
(6, 9, 0),
(8, 6, 0),
(8, 7, 0),
(8, 8, 0),
(8, 10, 0),
(15, 3, 0),
(15, 4, 0),
(15, 10, 0);
I need to select all term_id containing the number 8 and 5 (relationship between this numbers)
expected result = id 4 and id 8
I try this
SELECT `id` FROM `relationships` WHERE `term_id`=8 or `term_id`=5
but selects all term_id belong to 8 and 5
result = id 4 id 8 AND id --> 6 <-- This is not the result I want.

This does the job:
SELECT
id
FROM relationships a
WHERE
a.term_id = 5 AND
EXISTS (SELECT * FROM relationships b WHERE b.term_id = 8 AND b.id = a.id) > 0
demo: http://www.sqlfiddle.com/#!9/e78cc/4/0

Related

OR operator applying to entire WHERE clause

SELECT DISTINCT
customers.customer_id,
services.name
FROM users
INNER JOIN customers ON users.user_id=customers.user_id
LEFT JOIN appointments ON customers.customer_id=appointments.customer_id
INNER JOIN pets ON customers.customer_id=pets.customer_id
INNER JOIN services on appointments.service_id=services.service_id
WHERE ((appointments.customer_id IS NULL)
OR NOT (appointments.date > (SELECT SUBDATE(CURDATE(), 365)))
OR ((appointments.date > (SELECT SUBDATE(CURDATE(), 365)))
AND services.name NOT LIKE '%General Health Checkup%'))
GROUP BY customers.customer_id
I am trying to find all customers who are due a yearly general health checkup
this requires them to have:
a) never have appointments
b) not had an appointment in the past year
c) had an appointment in the past year but it wasn't a general health checkup
I assumed the final OR im my WHERE clause would only apply to that that operation i.e.
OR ((appointments.date > (SELECT SUBDATE(CURDATE(), 365))) AND services.name NOT LIKE '%General Health Checkup%'))
however it is ruling out all options for services named General Health Checkup.
How can i only apply this to that area of the where clause so that general health check up appointments can get through but only if they are from over a year ago.
Thanks !
appointments table:
CREATE TABLE `appointments` (
`appointment_id` int(8) NOT NULL,
`customer_id` int(8) DEFAULT NULL,
`service_id` int(4) DEFAULT NULL,
`staff_id` int(6) DEFAULT NULL,
`pet_id` int(9) DEFAULT NULL,
`date` date NOT NULL,
`start_time` time NOT NULL,
`status` enum('Open','Cancelled','Completed','') NOT NULL,
`create_date` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--
-- Dumping data for table `appointments`
--
INSERT INTO `appointments` (`appointment_id`, `customer_id`, `service_id`, `staff_id`, `pet_id`, `date`, `start_time`, `status`, `create_date`) VALUES
(1, 1, 2, 1, 1, '2017-03-22', '10:00:00', 'Completed', '2022-03-16 11:28:46'),
(2, 3, 2, 1, 6, '2021-06-18', '12:00:00', 'Completed', '2021-06-15 11:01:43'),
(3, 2, 2, 1, 2, '2020-07-17', '13:00:00', 'Completed', '2020-05-14 11:30:18'),
(4, 3, 2, 1, 5, '2020-07-10', '14:00:00', 'Completed', '2020-05-21 11:30:18'),
(5, 4, 3, 1, 7, '2020-09-17', '10:00:00', 'Completed', '2022-03-16 12:31:59'),
(6, 8, 2, 1, 11, '2022-03-17', '12:00:00', 'Cancelled', '2022-03-17 23:44:56'),
(7, 4, 2, 7, 7, '2022-03-17', '10:00:00', 'Cancelled', '2022-03-17 23:50:11'),
(8, 1, 1, 13, 1, '2022-03-17', '13:00:00', 'Completed', '2022-03-18 00:28:10'),
(9, 7, 2, 13, 9, '2022-03-18', '15:00:00', 'Cancelled', '2022-03-18 13:16:37'),
(10, 7, 1, 13, 10, '2022-03-18', '16:00:00', 'Cancelled', '2022-03-18 13:48:12'),
(11, 1, 1, 13, 1, '2022-03-22', '11:00:00', 'Completed', '2022-03-22 12:34:55'),
(12, 11, 1, 13, 11, '2022-03-23', '13:00:00', 'Completed', '2022-03-23 15:28:22'),
(13, 9, 3, 13, 12, '2022-03-26', '13:00:00', 'Completed', '2022-03-26 13:13:46'),
(14, 35, 2, 13, 16, '2022-03-27', '10:00:00', 'Completed', '2022-03-27 16:09:14'),
(15, 34, 2, 13, 20, '2022-03-28', '10:00:00', 'Completed', '2022-03-28 10:05:41'),
(16, 33, 1, 13, 20, '2022-03-28', '12:00:00', 'Completed', '2022-03-28 11:40:50'),
(17, 8, 2, 13, 20, '2022-03-16', '14:00:00', 'Completed', '2022-03-28 12:31:42'),
(18, 15, 2, 13, 20, '2022-03-28', '14:00:00', 'Completed', '2022-03-28 12:33:47'),
(19, 31, 4, 13, 20, '2022-03-29', '00:00:00', 'Completed', '2022-03-29 14:20:04'),
(20, 31, 4, 13, 20, '2022-03-29', '10:00:00', 'Completed', '2022-03-29 14:20:42'),
(21, 1, 1, 13, 1, '2022-03-30', '11:00:00', 'Completed', '2022-03-30 15:18:23'),
(22, 33, 4, 13, 22, '2022-03-30', '12:00:00', 'Completed', '2022-03-30 15:22:02'),
(23, 3, 1, 13, 5, '2022-03-30', '13:00:00', 'Open', '2022-03-30 15:22:02'),
(24, 4, 1, 13, 7, '2022-03-30', '13:30:00', 'Completed', '2022-03-30 15:24:52'),
(25, 7, 2, 13, 10, '2022-03-30', '14:30:00', 'Open', '2022-03-30 15:26:11'),
(26, 12, 1, 7, 8, '2022-04-21', '10:00:00', 'Open', '2022-04-21 12:54:10'),
(27, 2, 1, 1, 8, '2022-04-21', '10:00:00', 'Cancelled', '2022-04-21 13:16:23'),
(28, 17, 4, 1, 20, '2022-04-21', '10:00:00', 'Completed', '2022-04-21 13:18:41'),
(29, NULL, 6, 7, 21, '2022-04-21', '12:00:00', 'Completed', '2022-04-21 16:22:44'),
(30, 13, 2, 3, 5, '2022-04-21', '14:00:00', 'Open', '2022-04-21 17:42:10'),
(31, 5, 1, 9, 14, '2022-04-22', '11:00:00', 'Open', '2022-04-22 16:16:57');
services table:
CREATE TABLE `services` (
`service_id` int(4) NOT NULL,
`name` varchar(100) NOT NULL,
`description` text NOT NULL,
`average_time` int(3) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--
-- Dumping data for table `services`
--
INSERT INTO `services` (`service_id`, `name`, `description`, `average_time`) VALUES
(1, 'Consultation', 'General consultation to help you find the best path to good health for your pet.', 30),
(2, 'General Health Checkup', 'Review of your pets health.', 30),
(3, 'Microchip Insertion', 'Keep your dog safe and trackable with microchip.', 90),
(4, 'Puppy Vaccination', 'Initial puppy vaccination', 30),
(6, 'Booster Vaccination', 'Regular booster vaccincation service.', 30);
I would just check if the customer had a service_id=2 in the last year:
SELECT
customers.customer_id,
GROUP_CONCAT(CONCAT(services.name,'(',appointments.date,')')) as services
FROM users
INNER JOIN customers ON users.user_id=customers.user_id
LEFT JOIN appointments ON customers.customer_id=appointments.customer_id
INNER JOIN pets ON customers.customer_id=pets.customer_id
INNER JOIN services on appointments.service_id=services.service_id
WHERE SUBDATE(CURDATE(), 365) > (SELECT MAX(date)
FROM appointments
WHERE customers.customer_id=appointments.customer_id
AND appointments.service_id=2)
GROUP BY customers.customer_id
output:
customer_id
services
1
General Health Checkup(2017-03-22),Consultation(2022-03-30),Consultation(2022-03-22),Consultation(2022-03-17)
2
General Health Checkup(2020-07-17),Consultation(2022-04-21)
see: DBFIDDLE

SQL - adding total by searching for another value relating to the amount

been given this problem to solve
Write a function to get the payment sales figures from any given shop. The shop should be searched for by name.
i have this so far
SELECT shopname SUM ( amount ) AS sales
FROM frs_Shop, frs_Payment
WHERE shopname = "shop name"
i have the amount to add up but when i go to compile it adds up every amount in this table
INSERT INTO frs_Payment
(payid, amount, paydatetime, empnin, custid, pstatusid, ptid)
values
(101, "3.99", "2015-10-26 16:26:15", "NIN001", 1, 1, 1),
(95, "15.96", "2015-09-24 16:26:15", "NIN001", 1, 1, 1),
(102, "3.99", "2015-10-11 13:25:31", "NIN003", 2, 1, 1),
(11, "11.97", "2015-06-12 19:37:59", "NIN010", 3, 1, 1),
(7, "11.97", "2015-04-11 12:41:28", "NIN010", 3, 2, 4),
(8, "7.98", "2015-05-05 22:49:02", "NIN010", 3, 1, 1),
(32, "15.96", "2015-07-19 02:26:49", "NIN024", 5, 2, 4),
(83, "7.98", "2015-08-20 16:21:08", "NIN011", 5, 2, 4),
(6, "15.96", "2015-03-04 10:51:03", "NIN027", 6, 2, 4),
(17, "3.99", "2015-10-03 01:06:15", "NIN028", 6, 1, 1),
(39, "11.97", "2015-03-24 20:03:05", "NIN027", 6, 1, 1),
(103, "3.99", "2015-10-27 14:45:11", "NIN009", 7, 1, 1),
(62, "15.96", "2015-10-12 14:23:23", "NIN001", 8, 1, 1),
i want it to only add up the ones i specify with the empnin
You can use an explicit join, and a GROUP BY. I made an assumption on the primary/foreign key relationship between frs_Shop and frs_Payment.
SELECT s.shopname
, p.empnin
, SUM ( p.amount ) AS sales
FROM frs_Shop s
INNER JOIN frs_Payment p on s.empnin = p.empnin
WHERE s.shopname = "shop name"
GROUP BY s.shopname, p.empnin

MySQL query to limit maximums and minimums

I have the following table:
INSERT INTO `test_table` (`id`, `x`, `y`) VALUES (1, 0, 10), (2, 6, 10),
(3, 9, 10), (4, 2, 9), (5, 4, 9), (6, 3, 8), (7, 7, 8), (8, 9, 8),
(9, 0, 7), (10, 2, 7), (11, 5, 7), (12, 10, 7), (13, 2, 6), (14, 7, 6),
(15, 0, 5), (16, 4, 5), (17, 9, 5), (18, 1, 4), (19, 3, 4), (20, 5, 4),
(21, 10, 4), (22, 8, 3), (23, 3, 2), (24, 6, 2), (25, 2, 1), (26, 8, 1),
(27, 0, 0), (28, 5, 0), (29, 6, 0), (30, 10, 0);
and it represent the following picture:
The numbers in the red or pink cells represent the "id" and the coordinates for those cells are "x" and "y".
All I have to do is to come up with a query to show all the cells (only the red ones), excluding the 10 cell within the gray square.
So far I have this:
SELECT * FROM `test_table` WHERE
x between 0 and 10 and
x not between 2 and 8 and
y between 0 and 10 and
y not between 2 and 7
order by id ASC
LIMIT 30
Imagining that the grid goes bellow 0 and beyond 10 in both directions (not showing in the picture); the query must have way too many limits. Anyways, the output is not what I want because it only give me the cells in the corners (the ones within the green areas): 1, 3, 8, 27 and 30
another approach will be to subtract this query:
SELECT * FROM `test_table` WHERE
x between 2 and 8 and
y between 2 and 7
order by id ASC
LIMIT 30
from this one:
SELECT * FROM `test_table` WHERE
x between 0 and 10 and
y between 0 and 10
order by id ASC
LIMIT 30
...but once again; i am unable to do it :(
It just needs to exclude x[2:8],y[2,7].
Try this:
SELECT * FROM `test_table`
WHERE NOT(x between 2 and 8 AND y between 2 and 7);
Just to add the other "side" limits; the final query was implemented like this:
SELECT * FROM
`test_table` WHERE
x between 0 and 10 and
y between 0 and 10 and
not
(x between 2 and 8 and
y between 2 and 7)

SELECT query for TableA and TableB IF TableB.col value (0 OR 1) I create new columns for 0 and 1

I have a Table pictures
create table pictures (
picture_id int(10) unsigned NOT NULL AUTO_INCREMENT,
mall_id float NOT NULL,
shop_id float NOT NULL,
picture_islogo int(11) NOT NULL ,
picture_path varchar(255) NOT NULL,
PRIMARY KEY (picture_id)
) ;
Sample Data for pictures
INSERT INTO pictures VALUES
(1, -1, 1, 1, 'photo.jpg'),
(2, -1, 2, 1, 'photo.jpg'),
(3, -1, 3, 1, 'photo.jpg'),
(4, -1, 4, 1, 'photo.jpg'),
(5, -1, 5, 1, 'photo.jpg'),
(6, -1, 6, 1, 'photo.jpg'),
(7, -1, 7, 1, 'photo.jpg'),
(8, -1, 8, 1, 'photo.jpg'),
(9, -1, 9, 1, 'photo.jpg'),
(10, -1, 10, 1, 'photo.jpg'),
(11, -1, 11, 1, 'photo.jpg'),
(12, -1, 12, 1, 'photo.jpg'),
(13, -1, 13, 1, 'photo.jpg'),
(14, -1, 13, 0, 'photo.jpg');
and other table malls
create table malls (
mall_id float NOT NULL AUTO_INCREMENT,
user_id float NOT NULL,
mall_displaysname varchar(255) NOT NULL,
mall_description text NOT NULL,
mall_contact varchar(14) NOT NULL,
mall_logo_picture_id int(11) NOT NULL,
mall_background_picture_id int(11) NOT NULL,
PRIMARY KEY (mall_id)
);
Sample Data for malls
INSERT INTO malls VALUES
(1, 2, 'mall', 'description', '+60 12 3456789', 14, 36),
(2, 5, 'mall 2', 'description', '+60 12 3456789', 15, 37),
(3, 6, 'mall 3', 'description ', '+60 12 3456789', 16, 38),
(4, 13, 'Multimedia University', 'description ', '+60 12 3456789', 17, 39),
(5, 18, 'Setia Walk', 'description ', '+60 12 3456789', 18, 40),
(6, 20, 'Ampang Point', 'description ', '+60 12 3456789', 19, 41),
(7, 21, 'Alamanda Plaza', 'description ', '+60 12 3456789', 20, 42),
(8, 22, 'Subang Parade', 'description ', '+60 12 3456789', 21, 43),
(9, 26, 'مجمع العرب - جدة', 'description ', '+60 12 3456789', 22, 44);
Where mall_background_picture_id and mall_background_picture_id reference to pictures.picture_id and Depend on the value of pictures.picture_islogo (0: Logo, 1:background or others)
i want a query to that returns the pictures.picture_path depends on the value of pictures.picture_islogo (0: Logo, 1:background or others)
the data that I need to get
mall_id , mall_displaysname, mall_logo, mall_background , mall_description, and mall_contact
Where mall_logo is the photo_path of the condition
pictures.picture_islogo = 1
and same thing with **mall_background** but
picture_islogo = 0
AND
mall_logo_picture_id = picture_id
Put the extra condition into the join condition:
select * -- you can chose what columns you want
from malls m
left join pictures pl on m.mall_logo_picture_id = pl.picture_id
and pl.picture_isLogo = 1
left join pictures pb on m.mall_background_picture_id = pb.picture_id
and pb.picture_isLogo = 0
To have left joins, the extra conditions must be in the join condition, which is evaluated as the join is being made.
If you put them in the where clause, which is evaluated after the join is made, you force the outer join to be an inner join, because the join must be successful fur the extra condition to be true.

GROUP BY with only first row of sequence of one column?

at first here is the alpha version of what I want: http://sqlfiddle.com/#!2/45c89/2
However I don't want to count all representative_id, but only this rows with the lowest id, eg:
(`id`, `economy_id`, `representative_id`)
(1, 1, 5), <-this one, lowest id through the same economy_id=1
(2, 1, 6),
(3, 1, 7),
(4, 1, 8),
(5, 1, 3),
(6, 1, 4),
(7, 1, 1),
(8, 1, 2),
(9, 1, 102),
(10, 2, 7), <-this one, lowest id through the same economy_id=2
(11, 2, 8),
(12, 2, 102),
(13, 2, 1),
(14, 2, 2),
(15, 2, 3),
(16, 2, 4),
(17, 3, 3), <-this one, lowest id through the same economy_id=3
(18, 3, 4),
(19, 3, 1),
(20, 3, 2),
(21, 3, 102),
(22, 4, 1), <-this one, lowest id through the same economy_id=4
(23, 4, 2),
(24, 4, 102),
(25, 5, 1), <-this one, lowest id through the same economy_id=5
(26, 5, 2),
(27, 5, 102),
(28, 5, 7),
(29, 6, 1), <-this one, lowest id through the same economy_id=6
The output should be:
representative_id, count()
According to above example:
5, 1
7, 1
3, 1
1, 3
Is it possible only in SQL?
If I'm understanding your question correctly, I think this should work using min in a subquery and joining back to itself:
select s.representative_id, count(*)
from stl_parliament s
join
(
select min(id) minid
from stl_parliament
group by economy_id
) t on s.id = t.minid
group by s.representative_id
Updated Fiddle Demo
SELECT x.representative_id
, COUNT(*) total
FROM stl_parliament x
JOIN
( SELECT economy_id
, MIN(id) min_id
FROM stl_parliament
GROUP
BY economy_id
) y
ON y.economy_id = x.economy_id
AND y.min_id = x.id
GROUP
BY representative_id;
http://sqlfiddle.com/#!2/45c89/34
You question is a bit confusing.
is it what do you want?
http://sqlfiddle.com/#!2/a58c7/19
select count(economy_id), min_rep_id
from
(
SELECT economy_id, min(representative_id) as min_rep_id
from stl_parliament
GROUP BY economy_id
) as x
GROUP BY min_rep_id
A little complex but should work :
select m.col1, m.col2, count(m.col2) from (
select t.economy_id as col1, l.representative_id as col2 from stl_parliament l,
(select economy_id,MIN(id) as minid from stl_parliament GROUP BY economy_id) t
where t.economy_id=l.economy_id and t.minid=l.id) m group by m.col2
Lots of subqueries, I am not so good with joins
Please try the below query.
SELECT a.rep_id,count(a.rep_id)
FROM(Select min(id) as mid,representative_id as rep_id,economy_id
FROM stl_parliament
GROUP BY economy_id) as a
GROUP BY a.rep_id