How to compare tabels and get difference out - php

I have some problems to compare two of my tables. Usually I show my attempt how to solve a problem but here I do not know what to do. Normally, I do it in php. So i get all the information from 2 tables and then compare. But I would like to do it in MySQL. I hope you can help.
The first table, is my transactions table. This is the place where people have used their cards in restaurants.
The second table is my booking table. This is the place where people book reservations in restaurant.
I want to compare these tables, so i can get those who has NOT used their reservation
Transaction mySQL
SELECT t.*, em.* FROM transactions as t
left join exp_members as em on (t.cardid-10000000 = em.member_id)
left JOIN exp_member_data emd on em.member_id = emd.member_id ORDER BY t.created DESC
Transaction Table.
Trans_ID TransactionTime Name Restaurant
1852 2013-04-08 12:45:21 Christian La Canton
1851 2013-04-08 12:41:00 Zaz Parken
Booking mySQL
SELECT b.* from exp_menucard_booking as b;
Booking Table:
ID BookingTime Name NumberOfPeople Restaurant
270 2013-04-09 14:45:00 Christian 2 La Canton
269 2013-04-08 12:17:00 Toby 4 La Raz
As you can se, Toby from Booking table has not used his card (transaction tabel). How can i get him out of my tabel.

If you want to select all persons, who have already booked (there is an entry in booking table) but do not have an entry in the Transaction Table you could try this query:
SELECT *
FROM `Booking` B
WHERE NOT EXISTS (
SELECT *
FROM `Transaction` T
WHERE T.name = B.name
);
BTW it would be better, if you used some User_ID instead of name to identify the persons

This is how you can select all the records that didn't use the booking. It's called an excluding left join or left exclude join. http://www.magecorner.com/mysql-joins-explained/
I'm not sure if this would be faster than WHERE NOT EXISTS, but considering that has a subquery, I think this is faster.
SELECT emb.*
FROM exp_menucard_booking emb
LEFT JOIN transactions t
ON (
t.Name = emb.Name AND
t.Restaurant = emb.Restaurant
)
WHERE t.Trans_ID IS NULL

SELECT * FROM Booking WHERE NAME NOT IN (SELECT NAME FROM Transaction );

Related

How to create new table for the output of DISTINCT COUNT to be distributed in rows, not in column?

My query displays the DISTINCT count of buyers with corresponding ticketserial#. I need to automatically calculate the SOLD and BALANCE column and save into the database either into the existing table (table1) with the rows that corresponds to the ticketserial. I've already exhausted my brain and did google many times but I just can't figure it out. So I tried another option by trying to create a new table into the database for the output of DISTINCT COUNT but I didn't find any sample query to follow, so that I could just use INNER JOIN for that new table with table1, with that the PRINTED, SOLD are in the same table, thus I can subtract these columns to obtain the values for the BALANCE column.
Existing table1 & table2 are records in the database via html form:
Table1
Ticket Serial Printed Copies SOLD(sold) Balance
TS#1234 50 ?(should be auto ?
TS#5678 80 ?(should be auto ?
(so on and so forth...)
Table2
Buyer Ticket Serial
Adam TS#1234
Kathy TS#1234
Sam TS#5678
(so on and so forth...)
The COUNT DISTINCT outputs the qty. of sold tickets:
<td> <?php print '<div align="center">'.$row['COUNT(ticketserial)'];?></td>
...
$query = "SELECT *, COUNT(ticketserial) FROM buyers WHERE ticketsold != 'blank' GROUP BY
ticketserial ";
It's COUNT output looks like this:
Ticket Serial------Distinct Count
TS#1234 7
TS#5678 25
(so on and so forth...)
I tried to update the SOLD column and BALANCE column by UPDATE or INSERT and foreach loop but only the first row in table was updated.
Table1
Ticket Serial Printed Copies Sold Balance
TS#1234 50 **7** 0
TS#5678 80 **0** 0
TS#8911 40 **0** 0
(so on and so forth...)
Note: The fieldname "sold" in table1 is not the same with the fieldname "ticketsold" in table2 as the former is quantity and the later is ticketserials.
Your question is a bit hard to follow. However this looks like a left join on a aggregate query:
select
t1.ticket_serial,
t1.printed_copies,
coalesce(t2.sold, 0) sold,
t1.printed_copies - coalesce(t2.sold, 0) balance
from table1 t1
left join (
select ticket_serial, count(*) sold
from table2
group by ticket_serial
) t2 on t2.ticket_serial = t1.ticket_serial
If you are looking to update the main table:
update table1 t1
left join (
select ticket_serial, count(*) sold
from table2
group by ticket_serial
) t2 on t2.ticket_serial = t1.ticket_serial
set
t1.sold = coalesce(t2.sold, 0),
t1.balance = t1.printed_copies - coalesce(t2.sold, 0)
I would not actually recommend storing the sold and balance in the main table - this is derived information that can be easily computed when needed, and would be tedious to maintain. If needed, you could create a view using the first above SQL statement, which will give you an always up-to-date perspective at your data.

Order by inside loop PDO [duplicate]

I have a table which stores IDs and the city where the store is located.
I want to list all the stores starting with the stores that are in the city where there are the most stores.
TABLE
ID CITY
1 NYC
2 BOS
3 BOS
4 NYC
5 NYC
The output I want is the following since I have the most stores in NYC, I want all the NYC location to be listed first.
1 NYC
4 NYC
5 NYC
2 BOS
3 BOS
SELECT count(City), City
FROM table
GROUP BY City
ORDER BY count(City);
OR
SELECT count(City) as count, City
FROM table
GROUP BY City
ORDER BY count;
Ahh, sorry, I was misinterpreting your question. I believe Peter Langs answer was the correct one.
This one calculates the count in a separate query, joins it and orders by that count (SQL-Fiddle):
SELECT c.id, c.city
FROM cities c
JOIN ( SELECT city, COUNT(*) AS cnt
FROM cities
GROUP BY city
) c2 ON ( c2.city = c.city )
ORDER BY c2.cnt DESC;
This solution is not a very optimal one so if your table is very large it will take some time to execute but it does what you are asking.
select c.city, c.id,
(select count(*) as cnt from city c2
where c2.city = c.city) as order_col
from city c
order by order_col desc
That is, for each city that you come across you are counting the number of times that that city occurs in the database.
Disclaimer: This gives what you are asking for but I would not recommend it for production environments where the number of rows will grow too large.
SELECT `FirstAddressLine4`, count(*) AS `Count`
FROM `leads`
WHERE `Status`='Yes'
AND `broker_id`='0'
GROUPBY `FirstAddressLine4`
ORDERBY `Count` DESC
LIMIT 0, 8

MySQL Group running too slow

I have a 3 MySQL tables which I need to get results from and which are:
1. Towns
Fields Towncode and Townname
2. Students
Fields student_id,name,surname,address,streetcode,towncode,HeadOfFamily
3. Phonebank
Fields student_id,contacted,towncode
Now I need a mysql statement (a) to get the total number of households from the students table and also (b) the number of students contacted for that particular town.
up to step (a) I managed which and is extremely fast which is:
SELECT
t.towncode as towncode,
t.townname as townname,
(SELECT COUNT(*)
FROM students p
WHERE p.towncode=t.towncode
and p.student_hh='H') AS households
FROM
towns t
ORDER BY
t.towncode ASC
but I cannot manage to insert as well another SELECT STATEMENT to get the number of calls fr that particular town.
Can you kindly assist please?
Doing a per-record count on towns is probably hurting you. I would pre-query the students table first, THEN use that joined to the towns.
For indexes, I would have the following indexes
table index
towns ( towncode, townname )
students ( student_hh, towncode )
SELECT
t.towncode as towncode,
t.townname as townname,
TownCnts.households
FROM
towns t
JOIN ( SELECT
p.towncode,
COUNT(*) households
from
students p
where
p.student_hh = 'H'
group by
p.towncode ) as TownCnts
ON t.towncode = TownCnts.towncode
ORDER BY
t.towncode ASC
Assuming that the number of "calls" is the number of rows in the PhoneBank table with a particular town code, then you can add another subselect:
SELECT t.towncode as towncode, t.townname as townname,
(SELECT COUNT(*)
FROM students p
WHERE p.towncode = t.towncode and p.student_hh='H'
) AS households,
(SELECT COUNT(*)
FROM phonebank pb
WHERE pb.towncode = t.towncode
) AS calls
FROM towns t
ORDER BY t.towncode ASC ;
Your question is a little vague. It is possible that you want count(distinct studentid) in the second query, rather than count(*).
To optimize this query, create the following indexes:
towns(towncode)
students(towncode, student_hh)
phonebank(towncode)

MySQL Join and create new column value

I have an instrument list and teachers instrument list.
I would like to get a full instrument list with id and name.
Then check the teachers_instrument table for their instruments and if a specific teacher has the instrument add NULL or 1 value in a new column.
I can then take this to loop over some instrument checkboxes in Codeigniter, it just seems to make more sense to pull the data as I need it from the DB but am struggling to write the query.
teaching_instrument_list
- id
- instrument_name
teachers_instruments
- id
- teacher_id
- teacher_instrument_id
SELECT
a.instrument,
a.id
FROM
teaching_instrument_list a
LEFT JOIN
(
SELECT teachers_instruments.teacher_instrument_id
FROM teachers_instruments
WHERE teacher_id = 170
) b ON a.id = b.teacher_instrument_id
my query would look like this:
instrument name id value
--------------- -- -----
woodwinds 1 if the teacher has this instrument, set 1
brass 2 0
strings 3 1
One possible approach:
SELECT i.instrument_name, COUNT(ti.teacher_id) AS used_by
FROM teaching_instrument_list AS i
LEFT JOIN teachers_instruments AS ti
ON ti.teacher_instrument_id = i.id
GROUP BY ti.teacher_instrument_id
ORDER BY i.id;
Here's SQL Fiddle (tables' naming is a bit different).
Explanation: with LEFT JOIN on instrument_id we'll get as many teacher_id values for each instrument as teachers using it are - or just a single NULL value, if none uses it. The next step is to use GROUP BY and COUNT() to, well, group the result set by instruments and count their users (excluding NULL-valued rows).
If what you want is to show all the instruments and some flag showing whether or now a teacher uses it, you need another LEFT JOIN:
SELECT i.instrument_name, NOT ISNULL(teacher_id) AS in_use
FROM teaching_instrument_list AS i
LEFT JOIN teachers_instruments AS ti
ON ti.teacher_instrument_id = i.id
AND ti.teacher_id = :teacher_id;
Demo.
Well this can be achieved like this
SELECT
id,
instrument_name,
if(ti.teacher_instrument_id IS NULL,0,1) as `Value`
from teaching_instrument_list as til
LEFT JOIN teachers_instruments as ti
on ti.teacher_instrument_id = til.id
Add a column and check for teacher_instrument_id. If found set Value to 1 else 0.

Search for Room Availability in Bookings [PHP/MySQL]

I am programming a Hotel Reservation module. Now I have to connect an existing application to get the available rooms on a given range of dates. Please help me in this.
I am here posting the DB schema of the existing app (where the rooms and bookings info were stored).
rooms:
id
room_type
room_count
people
hotel_id
bookings:
id
from
to
name
email
people
dt
hotel_id
bookings_rooms
booking_id
room_id
quantity
I will give 3 inputs
Hotel ID
From Date
To Date
What I need is a list of room_id and max_qty_available
So, rooms aren't actually rooms, they are a type with a count. Does clear up a few things, although by rooms not being seperate entities it is very hard to prevent a change of rooms being eligable.
SELECT r.id, r.room_count - SUM(br.quantity ) AS max_qty_available
FROM rooms r
LEFT JOIN bookings b
ON b.hotel_id = r.hotel_id
AND b.from < <Date END>
AND b.to > <Date START>
LEFT JOIN booking_rooms br
ON br.room_id = r.id
AND br.booking_id = br.id
WHERE r.hotel_id = <Hotel ID>
I`m guessing what some of this parameters are, but here it goes:
Select id as room_id, room_Count as max_qty_available From Rooms Where
id Not in (Select room_id From Bookings_rooms Where booking_id
In (Select id From bookings Where from>=#FromDate And to <=#ToDate And hotel_id=#HotelID)
) And hotel_id = #HotelID
You can replace IN and NOT IN with Exists and Not exists if there is a performance issue. But not sure if Exists are supported in mysql.

Categories