Hi guys i am getting the error :
Exception Description: Syntax error parsing [SELECT u FROM Appointment U WHERE u.startDatetime BETWEEN :date1 AND :date2 INNER JOIN Users_appointment where u.ATTENDEES_USER_NAME LIKE :search].
[34, 105] The expression is not a valid conditional expression.
when i am trying to run the query
public List<Appointment> appointmentRangeSearch(Date startdatetime, Date endDate) {
Query q = em.createQuery("SELECT u FROM Appointment U WHERE u.startDatetime BETWEEN :date1 AND :date2 INNER JOIN Users_appointment where u.ATTENDEES_USER_NAME LIKE :search");
q.setParameter("search", "%" + searchString + "%");
q.setParameter("date1", startdatetime, TemporalType.TIMESTAMP);
q.setParameter("date2", endDate, TemporalType.TIMESTAMP);
return q.getResultList();
}
the idea is that i search for a range of dates in the appointment table and then see if there is a matching username in the users_appointment table and if so output this
what is going wrong ?
thanks
Wrong SQL syntax used. Please go through the SQL syntax. You need to add a JOINING clause using ON to tell mysql how to link appointment table with users_appointment table. I assume that you have userid column in both tables.
SELECT u FROM Appointment U INNER JOIN Users_appointment
ON u.userid = users_appointment.userid
WHERE u.startDatetime BETWEEN :date1 AND :date2
AND u.ATTENDEES_USER_NAME LIKE :search
Related
In Go, I write a query that gives me all data but I just want to data where products.id and clients.id are distinct.
What is the simile query I can write?
res := find.Model(&domain.Clients{}).
Select ("products.id product_id, products.name product_name,"+
" clients.id id, clients.name name, clients.logo, clients.address, "+
"clients.business_id, clients.num_of_employee, clients.email, clients.sns_link, clients.phone").
Joins("LEFT JOIN company_interests ON company_interests.client_id = clients.id").
Joins("LEFT JOIN products ON products.id = company_interests.product_id").
Where("products.id = ? ", productId).Find(&resp)
In Go when i write "Select Distinct" then rest query , it is not valid in go. So, i got an idea to write the query using "group by". In Go "group by" syntax can be used by "GROUP" syntax . So, finally bellow query works fine for me.
res := find.Model(&domain.Clients{}).
Select ("products.id product_id, products.name product_name,"+
" clients.id id, clients.name name, clients.logo, clients.address, "+
"clients.business_id, clients.num_of_employee, clients.email, clients.sns_link, clients.phone").
Joins("LEFT JOIN company_interests ON company_interests.client_id = clients.id").
Joins("LEFT JOIN products ON products.id = company_interests.product_id").
Where("products.id = ? ", productId).
Group("company_interests.client_id, company_interests.product_id" ).Find(&resp)
how to increase the performance of this mysql query
SELECT '' AS sharedid,
hubber_posts.userID AS postowner,
hubber_posts.*,
'' AS sharedby,
hubber_posts.userID AS userID,
hubber_posts.posted_date AS DATE,
'' AS sharebyusr,
'' AS sharebyusrimg,
Concat_ws(' ', firstname, lastname) AS fullname,
username AS postedBy,
hubber_user.image,
hubber_user.gender AS gender,
(SELECT accounttype
FROM hubber_user_security us
WHERE hubber_user.ID = us.userID
AND hubber_posts.userID = us.userID) AS accounttype,
'' AS sharebyusrtype
FROM hubber_posts
INNER JOIN hubber_user
ON hubber_posts.userID = hubber_user.ID
WHERE hubber_posts.status = 1
Your example code has a correlated subquery. MySQL performs poorly with those, as of late 2016.
Try converting it to a JOINed table.
SELECT all that stuff,
us.accounttype
FROM hubber_posts
JOIN hubber_user ON hubber_posts.userID = hubber_user.ID
LEFT JOIN hubber_user_security us ON hubber_user.ID = us.userID
WHERE hubber_posts.status = 1
I used LEFT JOIN. Without the LEFT, any rows without a matching entry in that table will be suppressed from the result set.
You query is essentially this:
SELECT . . .
(SELECT accounttype
FROM hubber_user_security us
WHERE u.ID = us.userID AND
p.userID = us.userID
) AS accounttype,
. . .
FROM hubber_posts p INNER JOIN
hubber_user u
ON p.userID = u.ID
WHERE p.status = 1 ;
For this query, the optimal indexes are:
hubber_posts(status, userId)
hubber_user(Id)
hubber_user_security(userId)
I would note that the subquery has an extra correlation condition that is not necessary -- the user ids are already equal. And, you run the risk of getting an error if there are multiple account types.
You may intend:
(SELECT GROUP_CONCAT(accounttype)
FROM hubber_user_security us
WHERE u.ID = us.userID
) as accounttypes,
My suggestion is to support a join where hubber_posts is the base table and the 2 other tables are joined using nested loops.
No need to index hubber_posts for the join.
hubber_user.ID should be a PK.
hubber_user_security.userID should be indexed (and defined as a FK references hubber_user.ID).
As for the WHERE clause - only if you have relatively few rows where hubber_posts.status = 1 then you should add an index on hubber_posts.status
P.s.
since the join contain the condition -
ON hubber_posts.userID = hubber_user.ID
There is no need to compare both hubber_posts.userID and hubber_user.ID to us.userID
I have a question regarding a two table join. In this case Table1 (booking table) and Table2 (Booking Entries).
I need a query to get all the rows from Table1 WHERE the member_id in Table2 (exists only here not in table1) and Vip_id in BOTH tables can be searched.
SELECT vb.* , DATE_FORMAT(vb.bookingdate, '%W %D %M') bookingdate, DATE_FORMAT(vb.bookingrsvp, '%W %D %M') bookingrsvp, concat(sl.state, ' - ', sl.store) store, sl.ADD1, sl.ADD2, sl.SUBURB, sl.PHONE , ve.vip_entry_leadid
FROM vip_booking vb
INNER JOIN storelocator sl ON (vb.storeid = sl.id )
LEFT JOIN vip_entries ve ON (vb.vipid = ve.vip_id AND ve.vip_entry_leadid = '" . $_GET["leadid"] . "')
WHERE vb.vipid = " . $_GET["vipid"] . "
AND DATE(vb.bookingdate) >= CURDATE()
AND ve.vip_entry_leadid IS NULL
AND ve.vip_id IS NULL
GROUP BY vb.storeid ORDER BY sl.state, sl.store
Basically what I am trying to achieve here is select ALL bookings from ALL Stores part of a particular VIP EVENT that the CURRENT LOGGED IN USER hasn't already had an entry too? If it was a single field ie. vip_entries.vip_id = vip_booking.vipid THEN that would be okm however a user can be in the entries table multiple times provided that it is a DIFFERENT event?
The above query works however I don't know if I have written it correctly as I would like to use joins and avoid sub-queries.
Can you post some sample data in the question please.
Your query appears to do a LEFT JOIN on vip_entries, and then checks for NULL in 2 fields to ensure no record is found (might be better to check the unique id field of vip_entries, if one exists). But you then bring back the value vip_entries.vip_entry_leadid which will always be null.
Further you are using GROUP BY store_id. This will bring back one row per store_id, but the other values will be from an undefined row for that store_id (in most databases this would fail). I suspect looking at your description you actually want to bring back one row per event / store id (which is probably a unique combination) in which case it would seem you do not need the GROUP BY.
The above query works however I don't know if I have written it correctly
Unfortunately, while preceding SQL works in MySQL, your query is not valid in ANSI SQL. Only GROUP BY column and aggregation function can be SELECTed
I would like to use joins and avoid sub-queries.
As far as I know without sub-queries, you can only fetch vb.storeid as follows
SELECT vb.storeid
FROM vip_booking vb
INNER JOIN storelocator sl ON (vb.storeid = sl.id )
LEFT JOIN vip_entries ve ON (vb.vipid = ve.vip_id AND ve.vip_entry_leadid = '$leadid')
WHERE vb.vipid = $vipid
AND DATE(vb.bookingdate) >= CURDATE()
AND ve.vip_entry_leadid IS NULL
AND ve.vip_id IS NULL
GROUP BY vb.storeid;
Proper SQL with sub-queries:
In my opinion Following query is formal SQL for what you want.
SELECT
vb.*,
DATE_FORMAT(vb.bookingdate, '%W %D %M') bookingdate,
DATE_FORMAT(vb.bookingrsvp, '%W %D %M') bookingrsvp,
CONCAT(sl.state, ' - ', sl.store) store,
sl.ADD1, sl.ADD2, sl.SUBURB, sl.PHONE , ve.vip_entry_leadid
FROM
(SELECT DISTINCT
vb.storeid
FROM
vip_booking vb
LEFT JOIN
vip_entries ve ON (vb.vipid = ve.vip_id AND ve.vip_entry_leadid = '" . $_GET["leadid"] . "'
WHERE
vb.vipid = " . $_GET["vipid"] . "
AND DATE(vb.bookingdate) >= CURDATE()
AND ve.vip_entry_leadid IS NULL
AND ve.vip_id IS NULL) x
INNER JOIN
storelocator sl ON (x.storeid = sl.id)
ORDER BY
sl.state, sl.store;
Hi guys i have the following search command
public List<User> advancedSearch(String searchString, String criteria, String ordering) {
Query q = em.createQuery("SELECT u FROM USERS U WHERE u.username LIKE :search ORDER BY u.username, order");
q.setParameter("search", "%" + searchString + "%");
q.setParameter("order", "%" + ordering + "%");
return q.getResultList();
}
i get the values of the searhString, criteria and ordering from the U.I, the aim is to produce a query that is fully customisable, however currently i am having issues with the ordering, how can i use the value from the U.I. (order) in the query, as currently it is not running like this
i guess you mixed between the column and the table with big letter U
you should use this
Query q = em.createQuery("SELECT u FROM USERS U WHERE U.username LIKE :search ORDER BY U.username");
U.username and not u.username
EDIT:
Query q = em.createQuery("SELECT u FROM USERS U WHERE u.username LIKE :search ORDER BY u.username " + ordering + ");
and remove that line
q.setParameter("order", "%" + ordering + "%");
you cant set DESC and ASC as parameters
I am creating a clock-in / clock-out system for employees.
There is a tbl_clockins which contains records of each clock-in/clock-out session with information on whether each session is paid, how late the employee was for that session or how much overtime they did, etc.
There is another table called tbl_user_work_settings where the manager can set which days employees are on holiday, or have taken off on sickness etc.
I am creating some reports where I need totals for each employee, e.g. total days taken as holiday by each employee wihin a given date range. I have a very long query which actually gets all the required information, but it is huge and somewhat inefficient. Is there any way to make it smaller/more efficient? Any help is appreciated.
// get total days worked, unpaid days, bank holidays, holidays, sicknesses
// and absences within given date range for given users
$sql = "SELECT us.username, daysWorked, secondsWorked,
unpaidDays, bankHolidays, holidays, sicknesses, absences
FROM
(SELECT username FROM users WHERE clockin_valid='1') us
LEFT JOIN (
SELECT username, selectedDate, count(isUnpaid) AS unpaidDays
FROM tbl_user_work_settings
WHERE isUnpaid = '1'
AND selectedDate>='$startDate'
AND selectedDate<='$endDate'
GROUP BY username
) u ON us.username=u.username
LEFT JOIN (
SELECT username, count(isBankHoliday) AS bankHolidays
FROM tbl_user_work_settings
WHERE isBankHoliday='1'
AND selectedDate>='$startDate'
AND selectedDate<='$endDate'
GROUP BY username
) bh ON us.username=bh.username
LEFT JOIN (
SELECT username, count(isHoliday) AS holidays
FROM tbl_user_work_settings
WHERE isHoliday='1'
AND selectedDate>='$startDate'
AND selectedDate<='$endDate'
GROUP BY username
) h ON us.username=h.username
LEFT JOIN (
SELECT username, count(isSickness) AS sicknesses
FROM tbl_user_work_settings
WHERE isSickness='1'
AND selectedDate>='$startDate'
AND selectedDate<='$endDate'
GROUP BY username
) s ON us.username=s.username
LEFT JOIN (
SELECT username, count(isOtherAbsence) AS absences
FROM tbl_user_work_settings
WHERE isOtherAbsence='1'
AND selectedDate>='$startDate'
AND selectedDate<='$endDate'
GROUP BY username
) a ON us.username=a.username
LEFT JOIN (
SELECT username, count(DISTINCT DATE(in_time)) AS daysWorked,
SUM(seconds_duration) AS secondsWorked
FROM tbl_clockins
WHERE DATE(in_time)>='$startDate'
AND DATE(in_time)<='$endDate'
GROUP BY username
) dw ON us.username=dw.username";
if(count($selectedUsers)>0)
$sql .= " WHERE (us.username='"
. implode("' OR us.username='", $selectedUsers)."')";
$sql .= " ORDER BY us.username ASC";
You can use SUM(condition) on a single use of the tbl_user_work_settings table:
// get total days worked, unpaid days, bank holidays, holidays, sicknesses
// and absences within given date range for given users
$sql = "
SELECT users.username,
SUM(ws.isUnpaid ='1') AS unpaidDays,
SUM(ws.isBankHoliday ='1') AS bankHolidays,
SUM(ws.isHoliday ='1') AS holidays,
SUM(ws.isSickness ='1') AS sicknesses,
SUM(ws.isOtherAbsence='1') AS absences,
COUNT(DISTINCT DATE(cl.in_time)) AS daysWorked,
SUM(cl.seconds_duration) AS secondsWorked
FROM users
LEFT JOIN tbl_user_work_settings AS ws
ON ws.username = users.username
AND ws.selectedDate BETWEEN '$startDate' AND '$endDate'
LEFT JOIN tbl_clockins AS cl
ON cl.username = users.username
AND DATE(cl.in_time) BETWEEN '$startDate' AND '$endDate'
WHERE users.clockin_valid='1'";
if(count($selectedUsers)>0) $sql .= "
AND users.username IN ('" . implode("','", $selectedUsers) . "')";
$sql .= "
GROUP BY users.username
ORDER BY users.username ASC";
By the way (and perhaps more for the benefit of other readers), I really hope that you are avoiding SQL injection attacks by properly escaping your PHP variables before inserting them into your SQL. Ideally, you shouldn't do that at all, but instead pass such variables to MySQL as the parameters of a prepared statement (which don't get evaluated for SQL): read more about Bobby Tables.
Also, as an aside, why are you handling integer types as strings (by enclosing them in single quote characters)? That's needless and a waste of resource in MySQL having to perform unnecessary type conversion. Indeed, if the various isUnpaid etc. columns are all 0/1, you can change the above to remove the equality test and just use SUM(ws.isUnpaid) etc. directly.
Put each table that would join in a temp table...
then create indexes on joinable fields of temp tables...
and make your query with temp tables.
Example:
SELECT username, selectedDate, count(isUnpaid) AS unpaidDays
INTO #TempTable1
FROM tbl_user_work_settings
WHERE isUnpaid = '1'
AND selectedDate>='$startDate'
AND selectedDate<='$endDate'
GROUP BY username
create clustered index ix1 on #TempTable1 (username)