SQL Server 2014 excluding rows - sql-server-2014

My query:
`SELECT gft_key,
DonorCustomer.cst_ind_full_name_dn as 'Full Name',
DonorCustomer.cst_ixo_title_dn as 'Job Title',
DonorCustomer.cst_org_name_dn as 'Organization',
DonorCustomer.cst_eml_address_dn as 'Email Address',
apl_code as 'Appeal Code',
cmp_code as 'Campaign Code',
prd_name as 'Product Name',
chp_name as 'Chapter Name',
adr_line1,
adr_line2,
adr_city as 'City',
adr_post_code as 'Zip Code',
adr_country as 'Country',
mem_member_type as 'Member Type',
ivd_amount_cp as 'Gift Amount',
fun_code as 'Purpose Code',
gty_type as 'Gift Type',
gft_date as 'Gift Date',
pay_trx_date,
case
when pay_trx_date is null then 'Not Paid' else 'Paid' end as 'Paid?'
FROM
np_gift
JOIN np_gift_type ON gft_gty_key=gty_key
JOIN np_constituent ON gft_dnr_cst_key=dnr_cst_key
JOIN co_customer DonorCustomer ON dnr_cst_key=DonorCustomer.cst_key
JOIN co_customer_x_address ON cst_cxa_key = cxa_key
JOIN co_address ON cxa_adr_key = adr_key
JOIN oe_product ON gft_fpc_prd_key=prd_key
LEFT JOIN np_purpose ON gft_fun_key=fun_key
LEFT JOIN np_campaign ON gft_cmp_key=cmp_key
LEFT JOIN np_appeal ON gft_apl_key=apl_key
JOIN ac_invoice_detail ON gft_ivd_key=ivd_key and ivd_void_flag=0
left outer join ac_payment_detail on pyd_ivd_key=ivd_key
left outer join ac_payment on pyd_pay_key=pay_key
left outer join ac_payment_info on pay_pin_key=pin_key
LEFT JOIN vw_client_uli_member_type ON dnr_cst_key=mem_cst_key
LEFT JOIN co_customer_x_customer ON cxc_cst_key_1 = DonorCustomer.cst_key and (cxc_end_date is null or datediff(dd,getdate(),cxc_end_date) >=0) and cxc_rlt_code='Chapter Member'
LEFT JOIN co_chapter ON cxc_cst_key_2=chp_cst_key
where (pay_trx_date >= '7/1/2017' or pay_trx_date is null)
order by gft_date`
Sample data that I get by running the query: Gift Date pay_trx_date
2013-11-18 2017-07-12
2013-11-29 NULL
2014-12-15 NULL
2017-06-30 NULL
2015-05-01 2017-07-01
By running the query above I accomplish the above result set. However, I want to exclude rows where the gift date is < '7/1/2017' and pay_trx_date is NULL (Just like the middle rows in my sample data) at the same time though I want to keep rows where the gift date is <= '7/1/2017' and pay_trx_date is not NULL (Just like the first or last row in my sample data)

You can use your current query as inner block and filter one time as per your requirement.
SELECT * FROM (
-- Your Current Query
) Q
WHERE gft_date <= '7/1/2017' AND pay_trx_date IS NOT NULL

Related

#1054 - Unknown column in 'on clause' whereas alias defined

here's my query which gives the error "#1054 - Unknown column 'request1.orgname' in 'on clause'":
SELECT request.orgname,
request1.API_name AS 'API name',
SUM(CASE WHEN request.username IS NULL
THEN request.projects_priced_count
else 0
END) AS 'API prices calls',
SUM(request.projects_priced_count) AS 'Total prices calls'
FROM prod_virida_pricing.request
LEFT OUTER JOIN (
SELECT api_key.name AS 'API_name',
api_key.orgname AS 'Organization',
date(expiry_date) AS 'API expiry date',
is_active AS 'Active org'
FROM prod_virida_auth.api_key
INNER JOIN prod_virida_auth.organization ON api_key.orgname = organization.orgname
WHERE api_key.blocked = 0
AND organization.is_active = 1) request1 ON request.orgname = request1.orgname
ORDER BY orgname
;
This will solve the problem
Better to use aliases(table1 & table2 in the e.g.) for different subqueries to reduce confusion for SQL to understand to understand the correct columns.
SELECT request.orgname AS 'Organization',
request1.API_name AS 'API name',
SUM(CASE WHEN request.username IS NULL
THEN request.projects_priced_count
else 0
END) AS 'API prices calls',
SUM(request.projects_priced_count) AS 'Total prices calls'
FROM prod_virida_pricing.request AS table1
LEFT OUTER JOIN (
SELECT api_key.name AS 'API_name',
api_key.orgname AS 'Organization',
date(expiry_date) AS 'API expiry date',
is_active AS 'Active org'
FROM prod_virida_auth.api_key
INNER JOIN prod_virida_auth.organization ON api_key.orgname = organization.orgname
WHERE api_key.blocked = 0
AND organization.is_active = 1) AS table2 ON table1.Organization= table2.Organization
ORDER BY table1.Organization
;

Combining an IF statement with current query

I've got the following query that's finding all subscribers between a certain date:
SELECT s.id as 'Subscription ID', s.customer_id as 'Customer ID', s.start_date as 'Start Date', s.status as 'Current Status', l.date 'Cancellation Date'
FROM subscriptions as s
LEFT JOIN subscriptionlog as l ON s.id=l.subscription_id
WHERE s.start_date >= 1559347200
AND s.start_date <= 1596239999
I've added the last column "Cancellation date" where I want to find the following:
l.event = 'subscription_cancelled'
If that exists for a subscriber can it output l.date but if it can't find it, can the column be left blank for that line? How can I incorporate an IF statement?
This looks like a job for CASE clause. You can put it in your select clause for if-else display issues. You can also put it in your WHERE clause for a more robust filter.
In your case:
SELECT
s.id as 'Subscription ID',
s.customer_id as 'Customer ID',
s.start_date as 'Start Date',
s.status as 'Current Status',
CASE
WHEN l.event = 'subscription_cancelled'
THEN l.date
ELSE NULL
END as 'Cancellation Date'
FROM subscriptions as s
LEFT JOIN subscriptionlog as l ON s.id=l.subscription_id
WHERE s.start_date >= 1559347200
AND s.start_date <= 1596239999

Mysql Query Optimization - Shared Query need to optimized

Please help me to optimize below Query -
SELECT DISTINCT
al.displayName AS 'Brand',
al.locationName AS 'Campus',
pg.groupName AS 'School Phase',
result.programName AS 'Grade',
pc.categoryName AS 'Grade Category',
result.batchName AS 'Intake',
result.periodName AS 'Period',
admission.id AS 'ADmission',
result.stdName AS 'Student Name',
usr.code AS 'Student Id',
result.courseName AS 'Subject',
result.courseVariant AS 'Subject Variant',
cc.categoryName AS 'Subject Category',
fac.printName AS 'Teacher',
result.planPrintName AS 'Scheme',
planRank.marksObtainedFrom AS 'Maximum Marks',
planRank.gradeObtainedFrom AS 'Maximum Grade',
planRank.obtainedMarks AS 'Subject Level Marks',
planRank.grade AS 'Subject Grade',
planRank.obtainedMarks AS 'Percentage',
planRank.status AS 'Result Status',
result.levelOnePrintName AS 'Type',
typeRank.effectiveMarks AS 'Type Marks',
typeRank.grade AS 'Type Grade',
typeRank.status AS 'Type Result Status',
result.levelTwoPrintName AS 'Sub Type',
subTypeRank.effectiveMarks AS 'Sub Type Marks',
subTypeRank.grade AS 'Sub Type Grade',
subTypeRank.status AS 'Sub Type Result Status',
result.levelThreePrintName AS 'Method',
result.effectiveMarks AS 'Method Marks',
result.grade AS 'Method Grade',
result.status AS 'Method Result Status',
CASE
WHEN evntDetail.eventName IS NULL THEN evnt.detailSequenceNumber
WHEN evntDetail.eventName IS NOT NULL THEN evntDetail.eventName
ELSE NULL
END AS 'Event',
eventMarks.effectiveMarks AS 'Event Marks',
eventMarks.finalGrade AS 'Event Grade'
FROM
marksheet AS result
INNER JOIN
admission AS admission ON admission.id = result.admissionId
INNER JOIN
users AS usr ON usr.id = result.studentId
INNER JOIN
academy_location AS al ON al.id = admission.academyLocationId
INNER JOIN
programs AS prgm ON prgm.id = result.programId
LEFT OUTER JOIN
program_group AS pg ON pg.id = prgm.programGroupId
LEFT OUTER JOIN
program_category AS pc ON pc.id = prgm.programCategoryId
LEFT OUTER JOIN
courses AS course ON course.id = result.courseId
LEFT OUTER JOIN
course_category AS cc ON cc.id = course.courseCategoryId
LEFT OUTER JOIN
program_batch_course_param AS param ON result.courseVariantId = param.courseVarientId
AND result.periodId = param.progBatchPeriodConfigId
LEFT OUTER JOIN
prog_batch_course_faculty AS pbcf ON pbcf.progBatchCourseParamId = param.id
LEFT OUTER JOIN
users AS fac ON fac.id = pbcf.facultyId
LEFT OUTER JOIN
evaluation_plan_rank AS planRank ON result.admissionId = planRank.admissionId
AND (result.courseVariantId = planRank.courseVariantId
OR planRank.courseVariantId IS NULL)
AND result.sectionId = planRank.sectionId
AND result.periodId = planRank.periodId
AND result.evaluationPlanId = planRank.evaluationPlanId
LEFT OUTER JOIN
evaluation_plan_level_one_rank AS typeRank ON result.admissionId = typeRank.admissionId
AND (result.courseVariantId = typeRank.courseVariantId
OR typeRank.courseVariantId IS NULL)
AND result.periodId = typeRank.periodId
AND result.sectionId = typeRank.sectionId
AND result.evaluationPlanLevelOneId = typeRank.evaluationPlanLevelOneId
LEFT OUTER JOIN
evaluation_plan_level_two_rank AS subTypeRank ON result.admissionId = subTypeRank.admissionId
AND (result.courseVariantId = subTypeRank.courseVariantId)
AND result.periodId = subTypeRank.periodId
AND result.sectionId = subTypeRank.sectionId
AND result.evaluationPlanLevelTwoId = subTypeRank.evaluationPlanLevelTwoId
INNER JOIN
eval_seq_detail AS evnt ON result.evaluationPlanThreeId = evnt.evalSequenceId
LEFT OUTER JOIN
examination_result AS eventMarks ON result.admissionId = eventMarks.admissionId
AND (result.courseVariantId = eventMarks.courseVariantId
OR eventMarks.courseVariantId IS NULL)
AND result.sectionId = eventMarks.sectionId
AND result.periodId = eventMarks.periodId
AND evnt.id = eventMarks.evaluationDetailSequenceId
LEFT OUTER JOIN
evaluation_type_course typeCourse ON eventMarks.courseVariantId = typeCourse.courseVariantId
AND eventMarks.periodId = typeCourse.periodId
LEFT OUTER JOIN
exam_event_detail evntDetail ON eventMarks.evaluationDetailSequenceId = evntDetail.eventId
AND evntDetail.evaluationTypeCourseId = typeCourse.id
WHERE
eventMarks.examResultStatus IS NOT NULL
AND result.evaluationPlanId IS NOT NULL
AND result.evaluationPlanLevelOneId IS NOT NULL
AND result.evaluationPlanLevelTwoId IS NOT NULL
AND result.evaluationPlanThreeId IS NOT NULL;
In tables marksheet = '740119' and examination_result = '4891575' approx records.
when I execute query then it will take around 10 min and also show time out error, as data-set is large.
I applied indexes on table's for performance but still Query take lots of time.
I applied Explain on Query to check status -
Add the keyword "STRAIGHT_JOIN" to you query. It looks like you have everything in proper logical alignment. You are querying from the main table and joining to all the lookup tables secondary. MySQL sometimes tries to optimize based on table row sizes and will look at a smaller table as a more beneficial path and can choke.
SELECT STRAIGHT_JOIN (rest of query)
Tells MySQL to do the query in the order you provided, don't think for me.
Now, that said, you don't really have a WHERE clause that may be taking advantage of an index. To prevent the need of having to go to every data page for the records, if you have an index on the where clauses, the engine can pre-qualify those records where not null via the index. Assuming that each evaluation plan is an integer (numeric) based "ID" value, I would add an index on
( evaluationPlanId, evaluationPlanLevelOneId, evaluationPlanLevelTwoId, evaluationPlanThreeId )

Display the list of people who is not present today from mysql query

I am trying to display the list of people who have
Case 1:
Forgotton to check-in and are present
Case 2:
Who are absent today and can't check-in today.
In both cases,check-in will be null because both have not checked-in
This is what I have achieved so far
SELECT
u.id,
u.`firstname` AS 'Firstname',
u.`lastname` AS 'Lastname',
ulr.leave_status AS 'Leave Status',
ulr.leave_from AS 'Leave From',
ulr.leave_to AS 'Leave To',
ulr.leave_description AS 'Leave Description',
DATE_FORMAT(
ulr.leave_from,
'%Y-%m-%d'
) AS 'Today''s Date'
FROM
users u
INNER JOIN users_leave_request ulr ON u.id = ulr.user_id
INNER JOIN checkin_checkout cc ON u.id = cc.users_id
WHERE
DATE_FORMAT(
leave_from,
'%Y-%m-%d'
) = CURDATE()
AND cc.checkin_time IS NULL
users_leave_request table: table1
checkin_checkout table: table2
This query will select all users that didn't checkin for today and if they had record in users_leave_request the data for that records will also be returned.
By using LEFT JOIN we avoid returning empty result for not checked-in user who don't have entry in users_leave_request. If we use JOIN, result will be returned only if records are found in both users and users_leave_request tables.
SELECT
u.id,
u.`firstname` AS 'Firstname',
u.`lastname` AS 'Lastname',
ulr.leave_status AS 'Leave Status',
ulr.leave_from AS 'Leave From',
ulr.leave_to AS 'Leave To',
ulr.leave_description AS 'Leave Description',
DATE_FORMAT(
ulr.leave_from,
'%Y-%m-%d'
) AS 'Today''s Date'
FROM users AS u
LEFT JOIN users_leave_request ulr ON u.id = ulr.user_id
WHERE u.id NOT IN (
SELECT u.id
FROM
users u
INNER JOIN checkin_checkout cc ON u.id = cc.users_id
WHERE
DATE_FORMAT(cc.checkin_time, '%Y-%m-%d') = CURDATE()
)

Mysql join on calculated max result

I have an existing query:
select ProductLinesID, ProductID, ProductName, ProductCatalog, ManufacturerName,
productMSDSStatus, productStatusDesc, productStatusIcon, DATE_FORMAT(dateAdded,'%d/%m/%Y') As dateAdded, DATE_FORMAT(ProductRevision,'%d/%m/%Y') as ProductRevision,
ManufacturerID, SupplierName, ProductID, DATE_FORMAT(dateLatestCheck, '%d/%m/%Y') as dateLatestCheck,s.SupplierID
from sds_productlines pl
right join sds_products p on p.ProductID = pl.productlinesProductID
left join sds_manufacturer m on p.ProductManufacturer = m.ManufacturerID
left join sds_product_status ps on p.productMSDSStatus = ps.productStatusID
left join sds_departments d on pl.ProductLinesDepartmentID = d.DepartmentID
left join sds_hospitals h on h.hospitalID = d.DepartmentHospitalID
left join sds_supplier s on s.SupplierID = pl.SupplierID
which is defined in a php page. I've been asked to add another parameter which is stored in another table, the problem is, on sds_product can have many "communications" which is basicly like a comment with a date_created. For example, if I wanted a list of communications for a given product, I would do:
select * from sds_product_comms as pc
join sds_comms c on pc.comms_id = c.comms_id
where prod_id = 2546
I wanted to do this directly in SQL, so is it possible to somehow make a sub query to stick these two together, without creating duplicate rows in the initial query.
For example I don't want 5 rows of the same product with the same max date_created.
desc sds_comms
'comms_id', 'int(10) unsigned', 'NO', 'PRI', '', 'auto_increment'
'method', 'int(10) unsigned', 'NO', '', '', ''
'dialogue', 'varchar(200)', 'NO', '', '', ''
'reply_id', 'int(10) unsigned', 'NO', '', '', ''
'comm_to', 'varchar(60)', 'NO', '', '', ''
'comm_from', 'varchar(60)', 'NO', '', '', ''
'man_id', 'int(10) unsigned', 'NO', '', '', ''
'supp_id', 'int(10) unsigned', 'NO', '', '', ''
'user_id', 'int(10) unsigned', 'NO', '', '', ''
'date_created', 'timestamp', 'NO', '', 'CURRENT_TIMESTAMP', ''
Sorry for the detail but its hard to get my head around it!
EDIT:
select ProductLinesID, ProductID, ProductName, ProductCatalog, ManufacturerName,
productMSDSStatus, productStatusDesc, productStatusIcon, DATE_FORMAT(dateAdded,'%d/%m/%Y') As dateAdded, DATE_FORMAT(ProductRevision,'%d/%m/%Y') as ProductRevision,
ManufacturerID, SupplierName, ProductID, DATE_FORMAT(dateLatestCheck, '%d/%m/%Y') as dateLatestCheck,s.SupplierID
,lastContact
from sds_productlines pl
right join sds_products p on p.ProductID = pl.productlinesProductID
left join sds_manufacturer m on p.ProductManufacturer = m.ManufacturerID
left join sds_product_status ps on p.productMSDSStatus = ps.productStatusID
left join sds_departments d on pl.ProductLinesDepartmentID = d.DepartmentID
left join sds_hospitals h on h.hospitalID = d.DepartmentHospitalID
left join sds_supplier s on s.SupplierID = pl.SupplierID
left join sds_product_comms pc on pc.prod_id = p.productID
left join (select comms_id, max(date_created) as lastContact from sds_comms group by comms_id ) as c2 on pc.comms_id = c2.comms_id
where productID=555;
would this be a correct way of doing it? With this method I'm getting different lastContact dates for the same productID :(
Try this:
select ProductLinesID, ProductID, ProductName, ProductCatalog, ManufacturerName,
productMSDSStatus, productStatusDesc, productStatusIcon, DATE_FORMAT(dateAdded,'%d/%m/%Y') As dateAdded, DATE_FORMAT(ProductRevision,'%d/%m/%Y') as ProductRevision,
ManufacturerID, SupplierName, ProductID, DATE_FORMAT(dateLatestCheck, '%d/%m/%Y') as dateLatestCheck,s.SupplierID,
c.date_created as lastContact
from sds_productlines pl
right join sds_products p on p.ProductID = pl.productlinesProductID
left join sds_manufacturer m on p.ProductManufacturer = m.ManufacturerID
left join sds_product_status ps on p.productMSDSStatus = ps.productStatusID
left join sds_departments d on pl.ProductLinesDepartmentID = d.DepartmentID
left join sds_hospitals h on h.hospitalID = d.DepartmentHospitalID
left join sds_supplier s on s.SupplierID = pl.SupplierID
left join sds_product_comms pc on pc.prod_id = p.productID
left join comms_id c on c.comms_id = pc.comms_id and c.date_created = (select max(date_created) from comms_id c2 where c2.comms_id = pc.comms_id)
where productID=555;
If I understand you correctly, you want a parameter that is in a table that is on the N end of a 1:N relationship and you want to have only 1 of each.
You can try grouping your data using GROUP BY.
Something like:
SELECT sds_product_comms.*, MAX(sds_comms.created_at) FROM sds_product_comms AS pc
JOIN sds_comms c ON pc.comms_id = c.comms_id
GROUP BY sds_product_comms.prod_id