I have the following 2 tables (student and attendance):
mysql> describe student;
+----------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------------+--------------+------+-----+---------+----------------+
| student_id | int(11) | NO | PRI | NULL | auto_increment |
| student_email | varchar(255) | YES | | NULL | |
| student_phone_number | varchar(255) | YES | | NULL | |
| parent_first_name | varchar(255) | NO | | NULL | |
| parent_last_name | varchar(255) | NO | | NULL | |
| parent_email | varchar(255) | NO | | NULL | |
| parent_phone_number | varchar(255) | NO | | NULL | |
| first_name | varchar(255) | NO | | NULL | |
| last_name | varchar(255) | NO | | NULL | |
| days_absent | int(11) | YES | | NULL | |
| days_tardy | int(11) | YES | | NULL | |
| class_id | int(11) | NO | MUL | NULL | |
+----------------------+--------------+------+-----+---------+----------------+
mysql> describe attendance;
+-----------------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+------------+------+-----+---------+-------+
| student_id | int(11) | NO | PRI | NULL | |
| class_id | int(11) | NO | PRI | NULL | |
| attendance_date | date | NO | PRI | NULL | |
| absent | tinyint(1) | YES | | NULL | |
| tardy | tinyint(1) | YES | | NULL | |
| note | text | YES | | NULL | |
+-----------------+------------+------+-----+---------+-------+
I want to check the attendance and email of all the children who are absent or tardy for the day. Is there a SQL statement I can use that can, for example, select the students from attendance with an absent/tardy value = 1, then using that student_id specified in the attendance table, pull all the student info from the student table where attendance.student_id = student.student_id?
just try exists
select student_email,student_phone_number from student std
where exists(
select 1 from attendance atd where std.student_id = atd.student_id
and (atd.absent =1 or atd.tardy =1)
)
just make sure you select all the info from student table and exists all the filter in attendance talbe. the condition is student_id.
Also if you need info from attendance talbe, then use join.
Related
I am working on a piece of code that runs a query against MySQL. The syntax is below:
SELECT `order`.`id` AS `id`,
IFNULL(product.main_name, product.name) AS `variant`,
`product`.`id` AS `product_id`,
`product`.`cost` AS `cost`,
ROUND(SUM(order.price), 2) AS `price`,
SUM(order.quantity) AS `quantity`,
`product`.`sku` AS `sku`,
ROUND(order.price/order.quantity, 2) AS `avg_price`,
`product`.`quantity` AS `qty_at_hand`,
`order`.`fulfillment_channel` AS `fulfillment_channel`,
0 as `returns`
FROM `order`
LEFT JOIN `product` ON product.sku = order.sku
WHERE (`order`.`account_id`=1)
AND (`order`.`item_status`<>'Cancelled')
AND (`order`.`purchase_date` >= $start_date)
AND (`order`.`purchase_date` <= $end_date)
GROUP BY `order`.`sku`
My order table:
| id | int(11) | NO | PRI | NULL | auto_increment |
| user_id | int(11) | NO | MUL | NULL | |
| account_id | int(11) | NO | MUL | NULL | |
| merchant_order_id | varchar(255) | NO | | NULL | |
| purchase_date | datetime | NO | | NULL | |
| updated_date | datetime | NO | | NULL | |
| order_status | varchar(255) | NO | | NULL | |
| product_name | varchar(255) | NO | | NULL | |
| sku | varchar(255) | NO | MUL | NULL | |
| item_status | varchar(255) | NO | | NULL | |
| quantity | int(11) | NO | | NULL | |
| currency | varchar(10) | NO | | NULL | |
| price | decimal(9,2) | YES | | 0.00 | |
| created_at | datetime | NO | | CURRENT_TIMESTAMP | |
| fulfillment_channel | varchar(255) | YES | | NULL | |
My product table:
| id | int(11) | NO | PRI | NULL | auto_increment |
| user_id | int(11) | NO | MUL | NULL | |
| account_id | int(11) | NO | MUL | NULL | |
| name | varchar(255) | NO | | NULL | |
| main_name | varchar(255) | YES | | NULL | |
| description | text | YES | | NULL | |
| listing_id | varchar(255) | YES | | NULL | |
| sku | varchar(255) | NO | MUL | NULL | |
| open_date | datetime | YES | | NULL | |
| price | decimal(9,2) | NO | | 0.00 | |
| quantity | int(11) | YES | | NULL | |
| supplier_id | int(11) | YES | | NULL | |
| active | tinyint(1) | NO | | 1 | |
| supplier_sku | varchar(255) | YES | | NULL | |
| upc | varchar(255) | YES | | NULL | |
| tag | varchar(255) | YES | | NULL | |
| cost | decimal(9,2) | NO | | 0.00 | |
| ean | int(11) | YES | | NULL | |
| min_order_qty | int(11) | YES | | NULL | |
The query is working fine. However, I would like to replace the QUERY with a stored procedure - a function would take three (3) arguments: start_date, end_date and a boolean flag called full.
I would like the full to be interpreted in a the following way:
- if full is set to false, return the same results query returns now;
- if full is set to true, return a row for each entry in the products table with quantity, price and average price returned as 0, if where fails merged with the query results - a row for each product, whether where were orders in the set period or not.
I was thinking about making a temporary table, then running an update on it and dumping the table after the data has been returned?
What would be the correct way to approach this?
Thank you
Add a UNION to this query and have it do an LEFT OUTER JOIN from Products to Orders table and in the WHERE clause check for full = true and only look for rows with Order.id is NULL. Union would only bring rows when full = true.
Prepare data in SELECT as you specified.
I want to be able to select classes that are starting on or after the next two hours up until the end of tomorrow's date but I am not sure of how to do this.
My current sql is below, I have only been able to select classes that are after today's date and after the current time. I want to be able to only return classes that start two hours after now up until the end of tomorrows date.
I am able to pass the current date and current time into my node.js function that will construct the sql statement. Also, I have access to moment.js library if I need to use this I could.
Any help would be appreciated.
SELECT DISTINCT b.name
, a.time
FROM class a
Inner join (SELECT class_id, count(clientid)
FROM bookings
GROUP BY class_id
HAVING count(clientid) < 10) as openClasses on
a.class_id = openClasses.class_id
JOIN class_detail b
ON a.class_id = b.id
JOIN branch c
ON a.branch_id = c.id
WHERE c.level <= ( SELECT d.level
FROM client d
WHERE d.facebook_id = 'xxxxxx'
)
AND a.date = '2016-08-17'
AND a.time >= '13.00.00';
My tables are as follows:
BOOKINGS
+-----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| id | bigint(20) | NO | PRI | NULL | |
| CLIENT_ID | int(11) | NO | | NULL | |
| CLASS_ID | int(11) | NO | | NULL | |
| STATUS | varchar(10) | NO | | NULL | |
+-----------+-------------+------+-----+---------+-------+
mysql> show fields from BRANCH;
+---------------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+-------------+------+-----+---------+----------------+
| id | int(10) | NO | PRI | NULL | auto_increment |
| NAME | char(50) | NO | | NULL | |
| CONTACT_NO | char(50) | YES | | NULL | |
| MAP_IMG_PATH | char(200) | YES | | NULL | |
| ADDRESS | char(200) | YES | | NULL | |
| LEVEL | int(2) | NO | | NULL | |
| LOCATION | int(10) | YES | | NULL | |
| SECTOR_NAME | varchar(45) | YES | | NULL | |
| SECTOR_MAP_IMG_PATH | char(200) | YES | | NULL | |
+---------------------+-------------+------+-----+---------+----------------+
mysql> show fields from CLIENT;
+--------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| id | int(10) | NO | PRI | NULL | |
| NAME | char(50) | NO | | NULL | |
| DOB | int(8) | NO | | NULL | |
| LOCAL_BRANCH | int(10) | YES | | NULL | |
| FACEBOOK_ID | char(50) | NO | | NULL | |
| START_DATE | int(8) | NO | | NULL | |
| EMAIL | char(50) | YES | | NULL | |
| PIN | int(4) | YES | | NULL | |
| END_DATE | int(8) | NO | | NULL | |
| LEVEL | int(2) | YES | | NULL | |
| TEL | varchar(20) | YES | | NULL | |
+--------------+-------------+------+-----+---------+-------+
mysql> show fields from CLASS_DETAIL;
+--------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| id | int(10) | NO | PRI | NULL | |
| NAME | char(50) | NO | | NULL | |
| DESCRIPTION | char(200) | NO | | NULL | |
| CATEGORY | varchar(4) | YES | | NULL | |
| ACHIEVE_TYPE | char(200) | YES | | NULL | |
| IMG_M | varchar(200) | YES | | NULL | |
| IMG_F | varchar(200) | YES | | NULL | |
+--------------+--------------+------+-----+---------+-------+
mysql> show fields from CLASS;
+-----------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| CLASS_ID | int(10) | YES | | NULL | |
| BRANCH_ID | int(10) | NO | | NULL | |
| DURATION | int(3) | YES | | NULL | |
| DATE | date | NO | | NULL | |
| TIME | time | NO | | NULL | |
| STATUS | char(1) | NO | | NULL | |
+-----------+---------+------+-----+---------+----------------+
7 rows in set (0.11 sec)
I have 3 tables person, account and subscription. Account belongs to Person as one to many and Account and Subscription are many to many.I need a sql which can select data from three tables.-
Person Tables
+----------------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| username | varchar(128) | NO | | NULL | |
| password | varchar(128) | NO | | NULL | |
| account_id | int(11) | NO | | NULL | |
+----------------------------+---------------+------+---------------+----------------+
Account table
+--------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| yearly_renew | tinyint(1) | NO | | NULL | |
| date_joined | date | NO | | NULL | |
| last_renewed | datetime | YES | | NULL | |
| signup | tinyint(1) | NO | | NULL | |
| reason | varchar(100) | YES | | NULL | |
| yearly_total | int(11) | YES | | NULL | |
| total | int(11) | YES | | NULL | |
+--------------+--------------+------+-----+---------+----------------+
Account-Subscription table
+-----------------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| account_id | int(11) | NO | MUL | NULL | |
| subscription_id | int(11) | NO | MUL | NULL | |
+-----------------+---------+------+-----+---------+----------------+
Subscription table
+-------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| subscription_type | varchar(150) | YES | | NULL | |
| hold | tinyint(1) | NO | | NULL | |
| start_date | date | YES | | NULL | |
| end_date | date | YES | | NULL | |
| amount_paid | double | YES | | NULL | |
| date_paid | date | YES | | NULL | |
| transaction_id | int(11) | YES | | NULL | |
| free | tinyint(1) | NO | | NULL | |
+-------------------+--------------+------+-----+---------+----------------+
Expecting output in a single query -
OUTPUT
+-----------+------------+--------------+
| person.id | account.id | subscription.id |
+-----------+------------+--------------+
| 10 | 11 | 20 |
| 15 | 32 | 45 |
| 23 | 43 | null |
+--------+---------+-----------------+
try this. it may works properly...
SELECT p.Id AS person.id
,p.account_id AS account.id
,acsub.subscription_id as subscription.id
FROM Person AS p
LEFT JOIN Account-Subscription AS acsub ON p.account_id=acsub.account_id
SELECT p.Id AS person.id
,p.account_id AS account.id
,acsub.subscription_id as subscription.id
FROM Person AS p
INNER JOIN
Account-Subscription AS acsub ON p.account_id=acsub.account_id
I have 4 tables as below ,i am trying to join these tables but the query is taking too long to execute.Please tell me how do i optimize this.
Trying to do below
1) using a sub query i am creating a table based on input date range
2) i require to group result based on bank then on district and then on state,so that i can filter results on front end as State-->District-->Bank
3) Also i need to avoid some junk data which i am doing using not like clause.
select substring(a.ifsc,1,4) as code,
s.new_state as state,
s.state_id as stid,
d.new_dist as dist,
b.ifbank as bank,
count(a.amt) as num,
sum(a.amt) as amt from
(SELECT * FROM mtr where orgdate between '$fdate_new' and '$tdate_new')
as a JOIN ifsc b on b.ifscd=a.ifsc
JOIN user c on a.excd=c.mtr
JOIN state_mapping s on b.state=s.org_state
JOIN dist_mapping d on b.dist=d.org_dist
where
s.state_id ='$stid' and
TRIM(d.new_dist) <> '' and
d.new_dist IS NOT NULL
group by bank,dist order by amt desc;
dist_mapping table
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| org_dist | varchar(20) | YES | | NULL | |
| new_dist | varchar(20) | YES | | NULL | |
+----------+-------------+------+-----+---------+-------+
ifsc table
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| ifscd | varchar(11) | NO | PRI | | |
| ifscbr | varchar(40) | YES | | NULL | |
| ifbank | varchar(40) | YES | | NULL | |
| newifsc | varchar(11) | YES | | NULL | |
| dist | varchar(20) | YES | | NULL | |
| state | varchar(20) | YES | | NULL | |
+---------+-------------+------+-----+---------+-------+
state_mapping table
+-----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| org_state | varchar(20) | YES | | NULL | |
| new_state | varchar(20) | YES | | NULL | |
| state_id | int(2) | YES | | NULL | |
+-----------+-------------+------+-----+---------+-------+
user table
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| excode | int(2) | YES | | NULL | |
| mtr | int(2) | YES | | NULL | |
| exname | varchar(40) | YES | | NULL | |
| country | varchar(10) | YES | | NULL | |
+---------+-------------+------+-----+---------+-------+
mysql> desc mtr;
+---------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+---------------------+------+-----+---------+-------+
| excd | int(2) | NO | PRI | 0 | |
| orgdate | date | YES | | NULL | |
| amt | double(12,2) | YES | | NULL | |
| obank | int(1) | YES | | NULL | |
| brcd | int(5) | YES | | NULL | |
| brname | varchar(40) | YES | | NULL | |
| rname | varchar(40) | YES | | NULL | |
| bname | varchar(40) | YES | | NULL | |
| baddr | varchar(60) | YES | | NULL | |
| mob | varchar(32) | YES | | NULL | |
| ifsc | varchar(12) | YES | | NULL | |
+---------+---------------------+------+-----+---------+-------+
Subquery takes more time compare to join Please try this
select substring(a.ifsc,1,4) as code,
s.new_state as state,
s.state_id as stid,
d.new_dist as dist,
b.ifbank as bank,
count(a.amt) as num,
sum(a.amt) as amt
From mtr as a
JOIN ifsc b on b.ifscd=a.ifsc and orgdate between '$fdate_new' and '$tdate_new'
JOIN user c on a.excd=c.mtr
JOIN state_mapping s on b.state=s.org_state
JOIN dist_mapping d on b.dist=d.org_dist
where
s.state_id ='$stid' and `enter code here`
TRIM(d.new_dist) <> '' and
d.new_dist IS NOT NULL
group by bank,dist order by amt desc;
I have the following four tables in my database:
+--------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+----------------+
| complex_id | int(11) | NO | PRI | NULL | auto_increment |
| complex_name | varchar(45) | NO | | NULL | |
+--------------+-------------+------+-----+---------+----------------+
+--------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+----------------+
| machine_id | int(11) | NO | PRI | NULL | auto_increment |
| complex_id | int(11) | NO | MUL | NULL | |
| machine_name | varchar(45) | NO | | NULL | |
+--------------+-------------+------+-----+---------+----------------+
+-----------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+---------+----------------+
| devices_id | int(11) | NO | PRI | NULL | auto_increment |
| machine_id | int(11) | NO | MUL | NULL | |
| description | varchar(255) | NO | | NULL | |
| location | varchar(255) | YES | | NULL | |
| verification | varchar(255) | YES | | NULL | |
| rack_num | varchar(8) | YES | | NULL | |
| section_num | varchar(8) | YES | | NULL | |
| color_or_number | varchar(16) | YES | | NULL | |
| normal_position | varchar(16) | YES | | NULL | |
+-----------------+--------------+------+-----+---------+----------------+
+------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+----------------+
| pnp_id | int(11) | NO | PRI | NULL | auto_increment |
| devices_id | int(11) | NO | MUL | NULL | |
| pnp_num | varchar(45) | NO | | NULL | |
+------------+-------------+------+-----+---------+----------------+
I am trying to get results formatted as follows (NULL values appear as blanks):
+------------+-------------+-----------------------+
| devices_id | description | pnpnum |
+------------+-------------+-----------------------+
| 1 | ex | 1234 |
| 2 | ex2 | 2345 |
| 3 | ex3 | |
| 4 | ex4 | 3456, 4567, 5678, 6879|
+------------+-------------+-----------------------+
Using the following SQL query,
SELECT *, GROUP_CONCAT(pnp.pnp_num separator ', ') pnpnum
FROM devices
JOIN pnp ON devices.devices_id = pnp.devices_id
WHERE devices.machine_id = 1
GROUP BY devices.devices_ID
ORDER BY devices.description;
my results are relatively close, however, I am unable to include a device if it has a null pnpnum.
+------------+-------------+-----------------------+
| devices_id | description | pnpnum |
+------------+-------------+-----------------------+
| 1 | ex | 1234 |
| 2 | ex2 | 2345 |
| 4 | ex4 | 3456, 4567, 5678, 6879|
+------------+-------------+-----------------------+
What is it that I am missing from my SQL statement that will allow me to include null values?
You need to use LEFT JOIN because even if there isn't a match, it will return all the results from the left table leaving the fields from the right table null.