I am in the process of developing an SQL query to let HeidiSQL display the calendar entries and connected contacts.
The appointments are included in the vtiger_activity table and the contacts in the vtiger_contactdetails table. A connection exists through the table "vtiger_crmentity".
SELECT a.subject
, a.activitytype
, a.date_start
, a.due_date
, a.time_start
, a.time_end
, d.firstname
, d.lastname
FROM vtiger_activity a
LEFT
JOIN vtiger_crmentity c
ON c.crmid = a.activityid
LEFT
JOIN vtiger_contactdetails d
ON d.contactid = c.crmid
WHERE a.due_date >= '2019-05-18' AND a.date_start <= '2019-05-23'
Result of Query: it shows the dates in the time period but in the columns where it should show the contact is everywhere only NULL The query I need it for a Android App. I expected firstname and lastname, because the data exists.
Does anyone know where I have my mistake?
Ever thank you for your help
Your LEFT JOINs are in the wrong order. If you want the names, they are from the details table, and that should be the first table in the FROM. You will also need to move the conditions to the ON.
Something like this:
SELECT d.firstname, d.lastname, a.subject, a.activitytype
a.date_start, a.due_date, a.time_start, a.time_end
FROM vtiger_contactdetails d LEFT JOIN
vtiger_crmentity c
ON d.contactid = c.crmid LEFT JOIN
vtiger_activity a
ON c.crmid = a.activityid AND
a.due_date >= '2019-05-18' AND
a.date_start <= '2019-05-23';
Related
I would like to retrieve SSRS data-driven subscription detail from the ReportServer DB. I am able to retrieve most of the detail from the table Subscriptions but I need the dataset information (SQL Query itself) which is used for Data-driven subscriptions.
Can I achieve that?
I was wondering the same thing recently and did some research + guessing. It's a complicated query but I believe this is what you're looking for. It will only show reports that ran in the last 30 days so you'll want to adjust it if you want everything.
The key here is the Subscriptions.DataSettings which is the field that contains the query you'll be looking for.
SELECT s.SubscriptionID, c.Name
, c.Type
,s.EventType
, c.Description
, u.UserName AS CreatedBy
, c.CreationDate
, c.ModifiedDate
, s.Description AS Subscription
, s.DeliveryExtension AS SubscriptionDelivery
, d.Name AS DataSource
, s.LastStatus
, s.LastRunTime
, s.Parameters
, sch.StartDate AS ScheduleStarted
, sch.LastRunTime AS LastSubRun
, sch.NextRunTime
, c.Path
,s.DataSettings
FROM Catalog c
INNER JOIN
Subscriptions s ON c.ItemID = s.Report_OID
INNER JOIN
DataSource d ON c.ItemID = d.ItemID
LEFT OUTER JOIN
Users u ON u.UserID = c.CreatedByID
LEFT OUTER JOIN
ReportSchedule rs ON c.ItemID = rs.ReportID
LEFT OUTER JOIN
Schedule sch ON rs.ScheduleID = sch.ScheduleID
WHERE (c.Type = 2)
and s.DataSettings is not null
and s.LastRunTime > getdate()-31
ORDER BY c.Name
I try to improve this query but I do not made successefully. I use a some left join and subquerys (I don't know another form) We try to get all bookings from users with certain status and the number of bookings multiples related with this booking and get from the log user the origin. The query is slow even if use a limit clausure. I Appreciate all the help can you give me.
This is the query:
SELECT DISTINCT b.uneaque_id, b.id, b.status, b.route_status, b.username, b.purpose, b.transfer, b.pickup_date, b.pickup_time, b.return_time, b.amount, b.default_location, b.start_address_route_comments, b.start_address_route, b.end_address_route_comments, b.end_address_route, u1.first_name, u1.last_name, b.transaction_Id, b.manual_payment, mr.AddressCount, lu.origin
FROM bookingdetails b
LEFT JOIN log_users lu ON lu.uneaque_id = b.uneaque_id AND lu.command_type = 'NEW BOOKING'
LEFT JOIN (
SELECT booking_id, COUNT(*) AS AddressCount FROM booking_multiple_rides GROUP BY booking_id
) mr ON b.id = mr.booking_id,
userdetails u1 WHERE b.username = u1.email
AND u1.user_status IN ('Active', 'Blocked', 'Not_Active')
AND b.default_location = 1
PD: Sorry for my english.
You have a ON b.id = mr.booking_id, userdetails u1 WHERE
you should change with a proper inner join
SELECT DISTINCT b.uneaque_id
, b.id, b.status
, b.route_status
, b.username
, b.purpose
, b.transfer
, b.pickup_date
, b.pickup_time
, b.return_time
, b.amount
, b.default_location
, b.start_address_route_comments
, b.start_address_route
, b.end_address_route_comments
, b.end_address_route
, u1.first_name
, u1.last_name
, b.transaction_Id
, b.manual_payment
, mr.AddressCount
, lu.origin
FROM bookingdetails b
LEFT JOIN log_users lu ON lu.uneaque_id = b.uneaque_id AND lu.command_type = 'NEW BOOKING'
LEFT JOIN (
SELECT booking_id
, COUNT(*) AS AddressCount
FROM booking_multiple_rides GROUP BY booking_id
) mr ON b.id = mr.booking_id
INNER JOIN userdetails u1 ON b.username = u1.email
AND u1.user_status IN ('Active', 'Blocked', 'Not_Active')
AND b.default_location = 1
and be sure you have proper index on
table bookingdetails a composite index on columns ( uneaque_id , id, default_location)
table log_users a composite index on columns (uneaque_id, command_type)
table userdetails a cmposite index on columns (email,user_status )
Tip 1.
Hiding a derived table in a LEFT JOIN is a prescription for sluggishness.
Replace
mr.AddressCount
with
( SELECT COUNT(*)
FROM booking_multiple_rides
WHERE booking_id = b.id
GROUP BY booking_id ) AS AddressCount
and get rid of the LEFT JOIN ( SELECT ... ) AS mr ON ..
Tip 2 Use explicit JOINs, no the old-fashioned "comma-join":
JOiN userdetails u1
ON b.username = u1.email
This won't help performance but it will make things clearer.
Tip 3: If you need an INNER JOIN (u1) after a LEFT JOIN, use parentheses. Else, put the inner joins first, then the left joins. This makes it easier to use, but may screw up the logic.
Tip 4: Don't use LEFT unless you need it. When you dont need it, it confuses the reader (and the Optimizer). (Again, no performance change.)
Tip 5: Why are you using DISTINCT? That takes an extra pass over all the resultset.
If those do not help enough, then provide SHOW CREATE TABLE so we can critique the indexes.
I am trying to generate a report that will display data from 3 tables as follows:
SELECT B.datepoll, B.clientID, B.badTerm, A.FullQuery,
B.badMessage, C.clientNAME, E.CURRENT_TERMS
FROM BadTerms AS B INNER JOIN
QueryTERMS AS A ON B.badTerm = A.QUERIES INNER JOIN
Clients AS C ON B.clientID = C.clientID INNER JOIN
(
SELECT CLIENTID,COUNT(QUERIES) AS CURRENT_TERMS FROM QueryTERMS WHERE
clientID = 'XXXXXX' GROUP BY CLIENTID) E ON
E.CLIENTID = A.CLIENTID
WHERE (CONVERT(VARCHAR(10), B.datepoll, 120) < CONVERT(VARCHAR(10), GETDATE(), 120))
AND (B.clientID = 'XXXXXX')
Basically what should be displayed is for a given datepoll, display all badTerms, fullQuery, badMessage, clientID, clientName and total terms. The clientID is common among all 3 tables and queries is common among BadTerms and QueryTerms.
I have everything fine except for the total count. It should only appear once and be the total queries in the QueryTerms table not the BadTerms table.
Any help appreciated.
Actually got it to work now:
SELECT B.datepoll, B.clientID, B.badTerm, A.FullQuery,
B.badMessage, C.clientNAME, E.CURRENT_TERMS
FROM BadTerms AS B INNER JOIN
QueryTERMS AS A ON B.badTerm = A.QUERIES INNER JOIN
Clients AS C ON B.clientID = C.clientID INNER JOIN
(
SELECT CLIENTID,COUNT(QUERIES) AS CURRENT_TERMS FROM QueryTERMS WHERE
clientID = 'XXXXXX' GROUP BY CLIENTID) E ON
E.CLIENTID = A.CLIENTID
WHERE (CONVERT(VARCHAR(10), B.datepoll, 120) < CONVERT(VARCHAR(10), GETDATE(), 120))
AND (B.clientID = 'XXXXXX')
I have a database schema like this picture:
I want to write a query that select data of all 6 tables and a field that indicate whether a specific user applied for a job or not.
I've tried:
SELECT j.id, j.expired_date, j.title, j.views, j.status
, j.unread, j.applicants, j.location, j.created_date
, j.contract_type, c.country
, group_concat(DISTINCT jp.page_name) AS fan_pages
, group_concat(DISTINCT jp.id_page) AS id_pages
, app.id AS applied
FROM jobs AS j
INNER JOIN country AS c ON c.id = j.country
LEFT JOIN job_pages AS jp ON jp.id_job = j.id
LEFT JOIN applications AS app ON app.id_job = j.id
LEFT JOIN resumes AS res ON res.id = app.id_resume
LEFT JOIN applicants AS alc ON alc.id = res.id_applicant
AND alc.id_user = 15
WHERE ( j.status = 0 )
AND ( j.expired_date = 0
OR j.expired_date > 1323228856 )
GROUP BY `j`.`id`
ORDER BY `j`.`id` desc
LIMIT 5 OFFSET 5
But it return a result that indicates a job was applied by any user. How can I rewrite this query?
-- Edit --
Below is a basic ERD for how it would be easier to track users who have applied to jobs. I made the relationship between User and Resume a 1:M, in case you wanted to track resume versions. If not, it should be a 1:1 relationship.
So given the ERD, you have a user apply to a job with a resume. If you want to make the resume optional, then you remove the Resume table from the M:M with Job and link directly to User.
Just some ideas...
-- Original --
Just some advice.
Seems to me that you may need to re-visit the schema design. It seems like the applicants table should be a pivot table between the users and jobs tables. The users and jobs table have a M:M relationship in that many users can apply to many jobs and many jobs can be applied to by many users. The applicants table should act as a transactional table when a user applies to a job.
Also, shouldn't the resumes table be directly linked to the users table? How can an application own a resume?
User owns a resume.
User applies to a job with a resume (applicant).
Try it,
SELECT j.id_user as creator, alc.id_user as applier, j.id , j.expired_date, j.title, j.views, j.status
, j.unread, j.applicants, j.location, j.created_date
, j.contract_type, c.country
, group_concat(DISTINCT jp.page_name) AS fan_pages
, group_concat(DISTINCT jp.id_page) AS id_pages
, MAX(app.id) AS applied
FROM jobs AS j
INNER JOIN country AS c ON c.id = j.country
LEFT JOIN job_pages AS jp ON jp.id_job = j.id
LEFT JOIN applications AS app ON app.id_job = j.id
LEFT JOIN resumes AS res ON res.id = app.id_resume
LEFT JOIN applicants AS alc ON alc.id = res.id_applicant
WHERE
( alc.id_user = 15 or alc.id_user IS NULL) AND
( j.status = 0 )
AND ( j.expired_date = 0
OR j.expired_date > 1323228856 )
GROUP BY `j`.`id`
ORDER BY `j`.`id` desc
UPDATE
I believe that, now the query is better:
SELECT
j.id, j.expired_date, j.title, j.views, j.status
, j.unread, j.applicants, j.location, j.created_date
, j.contract_type, c.country
, group_concat(DISTINCT jp.page_name) AS fan_pages
, group_concat(DISTINCT jp.id_page) AS id_pages
, max(app.id) AS applied
FROM users AS u
LEFT JOIN jobs AS j ON 1
INNER JOIN country AS c ON c.id = j.country
LEFT JOIN job_pages AS jp ON jp.id_job = j.id
LEFT JOIN applicants AS alc ON alc.id_user = u.id
LEFT JOIN resumes AS res ON res.id_applicant = alc.id
LEFT JOIN applications AS app ON app.id_resume = res.id AND app.id_job = j.id
WHERE u.id = 16 AND
( j.status = 0 )
AND ( j.expired_date = 0 OR j.expired_date > 1323228856 )
GROUP BY j.id
ORDER BY j.id
New updates:
Use MAX function if you want to get app.id because when you group one or more rows the max function will return correctly the id you want, else only first row will be return and it could be wrong with NULL
Join with the tables users and jobs
And join with applications should be with id_resume and id_job
I'm doing a LEFT JOIN on three tables, where the table "time" doesn't necessarily contain any matching rows. But if no matching rows is found in that table, the linked data disappears.
SELECT
w.date AS worker_date,
w.name AS worker_name,
w.address AS worker_address,
w.zip AS worker_zip,
w.place AS worker_place,
w.phone AS worker_phone,
w.email AS worker_email,
w.company AS worker_company,
w.accessibility AS worker_accessibility,
c.date AS client_date,
c.name AS client_name,
c.address AS client_address,
c.zip AS client_zip,
c.place AS client_place,
c.phone AS client_phone,
c.email AS client_email,
c.web AS client_web,
c.contact AS client_contact,
j.date AS job_date,
j.client_id,
j.worker_id,
j.name AS job_name,
j.description AS job_description,
j.type AS job_type,
j.status AS job_status,
j.proof AS job_proof,
j.deadline AS job_deadline,
j.price AS job_price,
j.final_client AS job_final_client,
SUM(t.hours) AS time_hours
FROM
jobs AS j
LEFT JOIN (
workers AS w,
clients AS c,
time AS t
) ON (
w.id = j.worker_id AND
c.id = j.client_id AND
j.id = t.job_id
) GROUP BY
j.id;
How can I make this work?
Thank you in advance.
add
WHERE t.job_id IS NOT NULL before GROUP BY
Try Replace
SUM(t.hours) AS time_hours
to
(SELECT IFNULL(SUM(t.hours),0) FROM time WHERE time.job_id=j.job_id) AS time_hours
And remove the time from the join
I think your basic query is correct (with the join under braces)
Just replace
SUM(t.hours) AS time_hours
with
SUM(if(t.hours is NULL,0,t.hours)) AS time_hours
I am not sure if this is the problem here, but the behavior of commas vs JOINs changed after a certain MySQL version. Try this
...
FROM jobs AS j LEFT JOIN workers AS w ON w.id = j.worker_id
LEFT JOIN clients AS c c.id = j.client_id
LEFT JOIN `time` AS t ON j.id = t.job_id
...
Also modify the SUM with IFNULL as #ajreal suggests.