SQL query too big - Can I merge this? - sql

I have the query below which seems to work, but it really feels like I should be able to do it in a simpler manner. Basically I have an orders table and a production_work table. I want to find all orders which are not complete, meaning either there's no entry for the order in the production_work table, or there are entries and the sum of the work equals what the order calls for.
SELECT q.* FROM (
SELECT o.ident, c."name" AS cname, s."name" as sname, o.number, o.created, o.due, o.name, o.ud, o.dp, o.swrv, o.sh, o.jmsw, o.sw, o.prrv, o.mhsw, o.bmsw, o.mp, o.pr, o.st
FROM orders o
INNER JOIN stations s on s.ident = o.station_id
INNER JOIN clients c ON s.client_id = c.ident
INNER JOIN (
SELECT p.order_id, SUM(p.ud) AS ud, SUM(p.dp) AS dp, SUM(p.swrv) AS swrv, SUM(p.sh) AS sh, SUM(p.jmsw) AS jmsw, SUM(p.sw) AS sw, SUM(p.prrv) AS prrv,
SUM(p.mhsw) AS mhsw, SUM(p.bmsw) AS bmsw, SUM(p.mp) AS mp, SUM(p.pr) AS pr, SUM(p.st) AS st
FROM production_work p
GROUP BY p.order_id
) pw ON o.ident = pw.order_id
WHERE o.ud <> pw.ud OR o.dp <> pw.dp OR o.swrv <> pw.swrv OR o.sh <> pw.sh OR o.jmsw <> pw.jmsw OR o.sw <> pw.sw OR o.prrv <> pw.prrv OR
o.mhsw <> pw.mhsw OR o.bmsw <> pw.bmsw OR o.mp <> pw.mp OR o.pr <> pw.pr OR o.st <> pw.st
UNION
SELECT o.ident, c."name" AS cname, s."name" as sname, o.number, o.created, o.due, o.name, o.ud, o.dp, o.swrv, o.sh, o.jmsw, o.sw, o.prrv, o.mhsw, o.bmsw, o.mp, o.pr, o.st
FROM orders o
INNER JOIN stations s on s.ident = o.station_id
INNER JOIN clients c ON s.client_id = c.ident
WHERE NOT EXISTS (
SELECT 1 FROM production_work p WHERE p.ident = o.ident
)
) q ORDER BY due DESC

Here's the query I ended up with:
WITH work_totals AS (
SELECT p.order_id, SUM(p.ud + p.dp + p.swrv + p.sh + p.jmsw + p.sw + p.prrv + p.mhsw + p.bmsw + p.mp + p.pr + p.st) AS total
FROM production_work p
GROUP BY p.order_id
), order_totals AS (
SELECT ident, SUM(ud + dp + swrv + sh + jmsw + sw + prrv + mhsw + bmsw + mp + pr + st) AS total
FROM orders
GROUP BY ident
)
SELECT o.ident, c."name" AS cname, s."name" as sname, o.number, o.created, o.due, o.name, o.ud, o.dp, o.swrv, o.sh, o.jmsw, o.sw, o.prrv, o.mhsw, o.bmsw, o.mp, o.pr, o.st
FROM orders o
INNER JOIN stations s on s.ident = o.station_id
INNER JOIN clients c ON s.client_id = c.ident
INNER JOIN order_totals ot ON o.ident = ot.ident
LEFT OUTER JOIN work_totals w ON o.ident = w.order_id
WHERE w.order_id IS NULL OR ot.total <> w.total

The two queries in your UNION are almost identical so you can merge them into a single query as follows. I just changed the JOIN to the pw subquery to be a OUTER LEFT JOIN - which has the same reslut as your union because I incldued an additional OR clause in the WHERE statement to return these orders that dont have a record in the pw sub-query.
SELECT o.ident, c."name" AS cname, s."name" as sname, o.number, o.created, o.due, o.name, o.ud, o.dp, o.swrv, o.sh, o.jmsw, o.sw, o.prrv, o.mhsw, o.bmsw, o.mp, o.pr, o.st
FROM orders o
INNER JOIN stations s on s.ident = o.station_id
INNER JOIN clients c ON s.client_id = c.ident
LEFT OUTER JOIN (
SELECT p.order_id, SUM(p.ud) AS ud, SUM(p.dp) AS dp, SUM(p.swrv) AS swrv, SUM(p.sh) AS sh, SUM(p.jmsw) AS jmsw, SUM(p.sw) AS sw, SUM(p.prrv) AS prrv,
SUM(p.mhsw) AS mhsw, SUM(p.bmsw) AS bmsw, SUM(p.mp) AS mp, SUM(p.pr) AS pr, SUM(p.st) AS st
FROM production_work p
GROUP BY p.order_id
) pw ON o.ident = pw.order_id
WHERE (o.ud <> pw.ud OR o.dp <> pw.dp OR o.swrv <> pw.swrv OR o.sh <> pw.sh OR o.jmsw <> pw.jmsw OR o.sw <> pw.sw OR o.prrv <> pw.prrv OR
o.mhsw <> pw.mhsw OR o.bmsw <> pw.bmsw OR o.mp <> pw.mp OR o.pr <> pw.pr OR o.st <> pw.st
)
OR pw.order_id IS NULL
ORDER BY due DESC

Queries of this form: Show rows which do not have a match in the other table.
Can be done like this:
select <columns>
from <table1>
left outer join <table2> on <join_condition>
where table2.column IS NULL
This will find rows from table1 which do not have anything in table2 matching the join condition.
For your summing query, I would do something like this...
select table1.order_number, total = sum(table2.order_amount)
from table1
left outer join table2 on table1.order_number = table2.order_number
group by order_number
having total < (some_number) OR total is null
That combines getting orders which have no matches, and getting orders with less than some total order_amount.

Related

SQL Performance Tuning for query with lots of table joins

I have some SQL, and I have been trying to make it as fast as possible. However, because we have tables with a large amount of data, the SQL takes a long time to run.
More info:
PostgreSQL 9.2.24 on x86_64-redhat-linux-gnu, compiled by gcc (GCC)
4.8.5 20150623 (Red Hat 4.8.5-28), 64-bit
Question
Are there any pointers that I can use to make this faster?
SELECT DISTINCT
trip.travel_order_num as order_num,
min(contact.fname || ' ' || contact.sname) as traveller,
min(agentcontact.fname || ' ' || agentcontact.sname) as agent,
min(employee.staff_code) as staff_code,
trip.projectnumber,
min(lob.name) as cost_centre,
trip.start_date,
trip.end_date,
DATE(trip.end_date) - DATE(trip.start_date) + 1 as number_of_days,
DATE(trip.start_date) - DATE(reqcreationdate) as days_requested_in_advance,
trip.created as tripcreationdate,
trip.recoverablecost,
tripstatus.name AS status,
trip.company_id,
trip.eventtypes,
trip.trip_reason,
min(to_char(timetofirstbooking.earliestbookingdate - trip.reqcreationdate, 'FMDD HH24:MI:SS')) as dates_taken_to_book,
min(COALESCE(paidaccommodation.paid_accomtot, 0.00)) AS paid_accomtot,
min(COALESCE(booked_accommodation_total, 0.00)) as booked_accommodation_total,
min(COALESCE(null, 0.00)) AS paid_cartot,
min(COALESCE(bookedcarhire.booked_car_hire_total, 0.00)) as booked_car_hire_total,
min(COALESCE(paidflightfare.allstatuses_flighttot, 0.00)) AS allstatuses_flighttot,
min(COALESCE(paidflightfare.savings, 0.00)) AS flightsavings_tot,
min(COALESCE(paidflightfare.publishedfare, 0.00)) AS flightpublishedfare_tot,
min(COALESCE(tripservicefeepaid.feeamount, 0.00)) as servicefee,
min(COALESCE(tripchangeservicefeepaid.feeamount, 0.00)) as changeservicefee,
min(COALESCE(otheritemspaid.amount, 0.00)) as otherfee,
CASE
WHEN trip.requester_personid IS NOT NULL THEN min(requestercontact.fname || ' ' || requestercontact.sname)
WHEN trip.requester_personid IS NULL THEN min(agentcontact.fname || ' ' || agentcontact.sname)
END as requester,
CASE
WHEN min(tas.lastname) IS NOT NULL AND min(tas.staffcode) IS NOT NULL THEN string_agg(DISTINCT(CONCAT(tas.firstname,' ',tas.lastname, ' (',tas.staffcode,')')),', ')
WHEN min(tas.lastname) IS NOT NULL THEN string_agg(DISTINCT(CONCAT(tas.firstname,' ',tas.lastname)),', ')
ELSE ''
END as approver,
min(bob.approvalRequestedDate) as approvalrequesteddate,
max(bob.apprConcDate) as approvalconclusiondate,
extract(EPOCH from min(timetoapprove))/3600 as timetoapprove
FROM TRIP
LEFT JOIN TRIPTRAVELLERMAP ON triptravellermap.tripid = trip.trip_id
LEFT JOIN FLIGHTFARE ON flightfare.triptravid = triptravellermap.triptravid
LEFT JOIN TRAVELAGENT ON travelagent.agentid = trip.agent_id
LEFT JOIN CONTACT as agentcontact ON agentcontact.member_id = travelagent.memberid
LEFT JOIN ITEM ON item.itemid = trip.itemid
LEFT JOIN LOB ON lob.lobid = item.lobid
LEFT JOIN TRIPSTATUS ON tripstatus.statusid = trip.status
LEFT JOIN PERSON_CONTACT ON person_contact.person_personid = triptravellermap.personid
LEFT JOIN CONTACT ON contact.contact_id = person_contact.personaldetails_contact_id
LEFT JOIN PERSON_EMPLOYEE ON person_employee.person_personid = triptravellermap.personid
LEFT JOIN EMPLOYEE ON employee.employee_id = person_employee.employmentdetails_employee_id
LEFT JOIN TRIPREQUIREMENTSMAPPING ON triprequirementsmapping.tripid = trip.trip_id
LEFT JOIN TRIPREQUIREMENTS ON triprequirements.uri = triprequirementsmapping.corporatetravelrequesturi
LEFT JOIN PERSON_CONTACT AS requesterperson ON requesterperson.person_personid = trip.requester_personid
LEFT JOIN CONTACT AS requestercontact ON requestercontact.contact_id = requesterperson.personaldetails_contact_id
LEFT JOIN trip_approver_snapshot tas ON trip.trip_id=tas.trip_id
/* PAID ACCOMMODATION */
LEFT JOIN (SELECT trip.trip_id, SUM(lineitems.amount) as paid_accomtot
FROM TRIP
INNER JOIN RESERVATION ON reservation.trip_id = trip.trip_id
INNER JOIN ACCOMMODATION ON accommodation.reservationid = reservation.reservationid
INNER JOIN LINEITEMS ON lineitems.invoiceid = accommodation.invoiceid
WHERE accommodation.created >= '2021-05-01' and accommodation.created <= ('2021-05-23')
AND accommodation.resstatus <> 2
GROUP BY trip.trip_id) AS paidaccommodation ON paidaccommodation.trip_id = trip.trip_id
/* BOOKED ACCOMMODATION */
LEFT JOIN (SELECT trip.trip_id, SUM(accommodation.totalaftertax) as booked_accommodation_total
FROM TRIP
INNER JOIN RESERVATION ON reservation.trip_id = trip.trip_id
INNER JOIN ACCOMMODATION ON accommodation.reservationid = reservation.reservationid
WHERE accommodation.created >= '2021-05-01' AND accommodation.created <= '2021-05-23'
AND accommodation.invoiceid IS NULL AND accommodation.resstatus <> 2
GROUP BY trip.trip_id) AS bookedaccommodation ON bookedaccommodation.trip_id = trip.trip_id
/* PAID CARRENTAL */
LEFT JOIN (SELECT trip.trip_id, SUM(carrental.rental_price) as booked_car_hire_total
FROM TRIP
INNER JOIN RESERVATION ON reservation.trip_id = trip.trip_id
INNER JOIN CARRENTAL ON carrental.reservationid = reservation.reservationid
WHERE carrental.created >= '2021-05-01' AND carrental.created <= '2021-05-23' AND carrental.status <> 2
GROUP BY trip.trip_id) AS bookedcarhire ON bookedcarhire.trip_id = trip.trip_id
/* PAID FLIGHT DETAILS */
LEFT JOIN ( SELECT trip.trip_id, SUM(flightfare.totalfare) as allstatuses_flighttot, SUM(flightfare.savings) as savings, SUM(flightfare.publishedfare) as publishedfare, MIN(flightfare.created) as earliestbooking
FROM TRIP
INNER JOIN TRIPTRAVELLERMAP ON triptravellermap.tripid = trip.trip_id
INNER JOIN FLIGHTFARE ON flightfare.triptravid = triptravellermap.triptravid
WHERE flightfare.created >= '2021-05-01' AND flightfare.created <= '2021-05-23'
AND (flightfare.status <> 2 OR (flightfare.status = 2 AND flightfare.ticketed = 1))
AND NOT(flightfare.ticketed = 0 AND flightfare.tickettimelimit < CURRENT_TIMESTAMP)
GROUP BY trip.trip_id ) AS paidflightfare ON paidflightfare.trip_id = trip.trip_id
/* TIME TO FIRST BOOKING */
LEFT JOIN (SELECT cc.trip_id, MIN(earliest_booked_date) as earliestbookingdate
FROM(
(SELECT trip.trip_id, MIN(flightfare.created) as earliest_booked_date
FROM TRIP
INNER JOIN TRIPTRAVELLERMAP ON triptravellermap.tripid = trip.trip_id
INNER JOIN FLIGHTFARE ON flightfare.triptravid = triptravellermap.triptravid
GROUP BY trip.trip_id )
UNION
(SELECT trip.trip_id, MIN(carrental.created) as earliest_booked_date
FROM TRIP
INNER JOIN RESERVATION ON reservation.trip_id = trip.trip_id
INNER JOIN CARRENTAL ON carrental.reservationid = reservation.reservationid
GROUP BY trip.trip_id)
UNION
(SELECT trip.trip_id, MIN(accommodation.created) as earliest_booked_date
FROM TRIP
INNER JOIN RESERVATION ON reservation.trip_id = trip.trip_id
INNER JOIN ACCOMMODATION ON accommodation.reservationid = reservation.reservationid
GROUP BY trip.trip_id)
) as cc GROUP BY cc.trip_id) AS timetofirstbooking ON timetofirstbooking.trip_id = trip.trip_id
/* TRIP FEES */
LEFT JOIN (SELECT trip.trip_id, SUM(tripfee.feeamount + tripfee.feeamountvat) as feeamount
FROM TRIP
INNER JOIN TRIPFEE ON tripfee.tripid = trip.trip_id
GROUP BY trip.trip_id) AS tripservicefeepaid ON tripservicefeepaid.trip_id = trip.trip_id
/* TRIP CHANGE FEES */
LEFT JOIN (SELECT trip.trip_id, SUM(tripfee.feeamount + tripfee.feeamountvat) as feeamount
FROM TRIP
INNER JOIN TRIPFEE ON tripfee.tripid = trip.trip_id
WHERE tripfee.tripfeetype = 9
GROUP BY trip.trip_id) AS tripchangeservicefeepaid ON tripchangeservicefeepaid.trip_id = trip.trip_id
/* OTHER ITEMS PAID */
LEFT JOIN (SELECT trip.trip_id, SUM(otheritems.amount + otheritems.vat) as amount
FROM TRIP
INNER JOIN OTHERITEMS ON otheritems.tripid = trip.trip_id
GROUP BY trip.trip_id) AS otheritemspaid ON otheritemspaid.trip_id = trip.trip_id
LEFT JOIN (
SELECT requested,max(conclusiondate) as apprConcDate , max(requestedDate) as approvalRequestedDate, max(conclusiondate)- max(requestedDate) as timetoapprove
FROM approvalsubmission
left join triprequirements on approvalsubmission.requested=triprequirements.uri
where approvalsubmission.conclusion='APPROVED'
group by requested) as bob on bob.requested = triprequirements.uri
WHERE
trip.trip_id IN (SELECT DISTINCT(trip_id) FROM reservation WHERE reservation.created >= ('2021-05-01') AND reservation.created <= ('2021-05-23'))
--AND LOWER(employee.staff_code) LIKE LOWER('$P!{staffCode')
AND trip.status <> 2
AND trip.company_id = 6632
--AND $P!{costCentreCompanySwitcher}
group by trip.trip_id, tripstatus.name
ORDER BY min(lob.name)
Fixed:
remove the status from the group by clause:
max(tripstatus.name) AS status,
...
group by trip.trip_id

Pull a separate column that matches the (min) of an aggregate function

It works well so far but I am stumped from here as I am brand new to this. This query finds the closest distance match, pairing up every item in the "FAILED" folder against everything that isn't in the "FAILED" folder.
There is a column "RouteID" in the "table p" that I want to match up with the min() aggregate.
I cannot process how to make the SELECT query simply show the associated "RouteID" column from tbl p but ultimately, I want to turn this into an update query that will SET a.Route = p.Route that is associated with the min()
Any help would be appreciated.
SELECT a.name, a.Reference1,
MIN(round(ACOS(COS(RADIANS(90-a.lat))
*COS(RADIANS(90-p.latpoint))
+SIN(RADIANS(90-a.lat))
*SIN(RADIANS(90-p.latpoint))
*COS(RADIANS(a.lon-p.longpoint)))
*3958.756,2)) AS 'DISTANCE'
FROM tblOrder AS a WITH (NOLOCK)
LEFT JOIN
(
SELECT b.lat AS latpoint, b.lon AS longpoint,
b.Sequence, b.routeid
from tblOrder b WITH (NOLOCK)
WHERE b.CUSTID = 180016
AND b.routeID <> 'FAILED'
AND b.StopType = 1
) AS p ON 1=1
WHERE a.CustID = 180016
AND a.RouteID = 'FAILED'
AND a.StopType = 1
AND P.RouteID <> 'FAILED'
GROUP BY
a.name, a.Reference1
You can select them separately and then join them
SELECT c.name, c.Reference1, q.RouteID
FROM
(
SELECT a.name, a.Reference1,
MIN(round(ACOS(COS(RADIANS(90-a.lat))
*COS(RADIANS(90-p.latpoint))
+SIN(RADIANS(90-a.lat))
*SIN(RADIANS(90-p.latpoint))
*COS(RADIANS(a.lon-p.longpoint)))
*3958.756,2)) AS 'DISTANCE'
FROM tblOrder AS a WITH (NOLOCK)
LEFT JOIN
(
SELECT b.lat AS latpoint, b.lon AS longpoint,
b.Sequence, b.routeid
from tblOrder b WITH (NOLOCK)
WHERE b.CUSTID = 180016
AND b.routeID <> 'FAILED'
AND b.StopType = 1
) AS p ON 1=1
WHERE a.CustID = 180016
AND a.RouteID = 'FAILED'
AND a.StopType = 1
AND P.RouteID <> 'FAILED'
GROUP BY
a.name, a.Reference1
) c
LEFT JOIN
(
SELECT b.lat AS latpoint, b.lon AS longpoint,
b.Sequence, b.routeid
from tblOrderRouteStops b WITH (NOLOCK)
WHERE b.CUSTID = 180016
AND b.routeID <> 'FAILED'
AND b.StopType = 1
) AS q
ON q.routeID = c.DISTANCE

Probably subquerys and not joins

This big query below returns me 2860 records and its correct number. I'm getting. The thing is that I need to add to this query invoice lines and make the same thing as I did with sale_order_lines "sum(l.price_subtotal / COALESCE(cr.rate, 1.0)) AS price_subtotal". I need to get the sum of price_subtotal of invoice lines.
so my first thought was to join tables like this.
JOIN sale_order_invoice_rel so_inv_rel on (so_inv_rel.order_id = s.id )
JOIN account_invoice inv on (inv.id = so_inv_rel.invoice_id and inv.state in ('open','paid'))
JOIN account_invoice_line ail on (inv.id = ail.invoice_id)
and then
sum(ail.price_subtotal / COALESCE(cr.rate, 1.0)) as price_subtotal
but after the first JOIN number of lines, I'm selecting is changing and even if I joins are done the numbers are way off basically I get 5x2860. So probably I need to make some subquery but at this point, I don't know how and asking for help.
WITH currency_rate AS (
SELECT r.currency_id,
COALESCE(r.company_id, c.id) AS company_id,
r.rate,
r.name AS date_start,
( SELECT r2.name
FROM res_currency_rate r2
WHERE r2.name > r.name AND r2.currency_id = r.currency_id AND (r2.company_id IS NULL OR r2.company_id = c.id)
ORDER BY r2.name
LIMIT 1) AS date_end
FROM res_currency_rate r
JOIN res_company c ON r.company_id IS NULL OR r.company_id = c.id
)
SELECT min(l.id) AS id,
l.product_id,
l.color_id,
l.product_size_id,
t.uom_id AS product_uom,
sum(l.product_uom_qty / u.factor * u2.factor) AS product_uom_qty,
sum(l.qty_delivered / u.factor * u2.factor) AS qty_delivered,
sum(l.qty_invoiced / u.factor * u2.factor) AS qty_invoiced,
sum(l.qty_to_invoice / u.factor * u2.factor) AS qty_to_invoice,
sum(l.price_total / COALESCE(cr.rate, 1.0)) AS price_total,
l.price_unit / COALESCE(cr3.rate, 1.0) AS price_total_by_cmp_curr,
sum(l.price_subtotal / COALESCE(cr.rate, 1.0)) AS price_subtotal,
count(*) AS nbr,
s.date_order AS date,
s.state,
s.partner_id,
s.user_id,
s.company_id,
date_part('epoch'::text, avg(date_trunc('day'::text, s.date_order) - date_trunc('day'::text, s.create_date))) / (24 * 60 * 60)::numeric(16,2)::double precision AS delay,
t.categ_id,
s.pricelist_id,
s.project_id AS analytic_account_id,
s.team_id,
p.product_tmpl_id,
partner.country_id,
partner.commercial_partner_id
FROM sale_order_line l
JOIN sale_order s ON l.order_id = s.id
JOIN res_partner partner ON s.partner_id = partner.id
LEFT JOIN product_product p ON l.product_id = p.id
LEFT JOIN product_template t ON p.product_tmpl_id = t.id
LEFT JOIN product_uom u ON u.id = l.product_uom
LEFT JOIN product_uom u2 ON u2.id = t.uom_id
LEFT JOIN res_company rc ON rc.id = s.company_id
LEFT JOIN product_pricelist pp ON s.pricelist_id = pp.id
LEFT JOIN currency_rate cr ON cr.currency_id = pp.currency_id AND cr.company_id = s.company_id AND cr.date_start <= COALESCE(s.date_order::timestamp with time zone, now()) AND (cr.date_end IS NULL OR cr.date_end > COALESCE(s.date_order::timestamp with time zone, now()))
LEFT JOIN currency_rate cr3 ON cr.currency_id = rc.currency_id AND cr.company_id = s.company_id AND cr.date_start <= COALESCE(s.date_order::timestamp with time zone, now()) AND (cr.date_end IS NULL OR cr.date_end > COALESCE(s.date_order::timestamp with time zone, now()))
GROUP BY l.product_id, t.uom_id, t.categ_id, s.date_order, s.partner_id, s.user_id, s.state, s.company_id, s.pricelist_id, s.project_id, s.team_id, l.color_id, cr3.rate, l.price_unit, l.product_size_id, p.product_tmpl_id, partner.country_id, partner.commercial_partner_id;
You can add the part that could be in a subquery to the with statement you already have to avoid the increase in number of lines, like so:
WITH currency_rate AS (
SELECT r.currency_id,
COALESCE(r.company_id, c.id) AS company_id,
r.rate,
r.name AS date_start,
( SELECT r2.name
FROM res_currency_rate r2
WHERE r2.name > r.name AND r2.currency_id = r.currency_id AND (r2.company_id IS NULL OR r2.company_id = c.id)
ORDER BY r2.name
LIMIT 1) AS date_end
FROM res_currency_rate r
JOIN res_company c ON r.company_id IS NULL OR r.company_id = c.id
)
, order_line_subtotal AS(
SELECT so_inv_rel.order_id, sum(ail.price_subtotal) as price_subtotal
FROM sale_order_invoice_rel so_inv_rel
JOIN account_invoice inv on (inv.id = so_inv_rel.invoice_id and inv.state in ('open','paid'))
JOIN account_invoice_line ail on (inv.id = ail.invoice_id)
GROUP BY so_inv_rel.order_id )
SELECT min(l.id) AS id,
....
From there it should be straightforward to add to the query without increasing the number of rows (since from the joins you already have a row for each order before the aggregation / group by.

Too many results in query

I'm fetching some data from our database in MSSQL. Out of this data I want to determine who created the client entry and who took the first payment from this client.
There can be many payment entries for a client on a single booking/enquiry and at the moment, my query shows results for each payment. How can I limit the output to only show the first payment entry?
My query:
SELECT
c.FirstName,
c.LastName,
c.PostalCode,
o.OriginOfEnquiry,
s.SuperOriginName,
c.DateOfCreation,
DATEDIFF(day, c.DateOfCreation, p.DateOfCreation) AS DaysToPayment,
pc.PackageName,
CONCAT(u.FirstName, ' ', u.LastName) AS CreateUser,
(SELECT CONCAT(u.FirstName, ' ', u.LastName)
WHERE u.UserID = p.UserID ) AS PaymentUser
FROM tblBookings b
INNER JOIN tblPayments p
ON b.BookingID = p.BookingID
INNER JOIN tblEnquiries e
ON e.EnquiryID = b.EnquiryID
INNER JOIN tblCustomers c
ON c.CustomerID = e.CustomerID
INNER JOIN tblOrigins o
ON o.OriginID = e.OriginID
INNER JOIN tblSuperOrigins s
ON s.SuperOriginID = o.SuperOriginID
INNER JOIN tblBookingPackages bp
ON bp.bookingID = p.BookingID
INNER JOIN tblPackages pc
ON pc.PackageID = bp.packageID
INNER JOIN tblUsers u
ON u.UserID = c.UserID
WHERE c.DateOfCreation >= '2016-06-01' AND c.DateOfCreation < '2016-06-30'
AND p.PaymentStatusID IN (1,2)
AND e.CustomerID = c.CustomerID
AND p.DeleteMark != 1
AND c.DeleteMark != 1
AND b.DeleteMark != 1
;
I tried adding a "TOP 1" to the nested select statement for PaymentUser, but it made no difference.
you can use cross apply with top 1:
FROM tblBookings b
cross apply
(select top 1 * from tblPayments p where b.BookingID = p.BookingID) as p
Instead of table tblPayments specify sub-query like this:
(SELECT TOP 1 BookingID, UserID, DateOfCreation
FROM tblPayments
WHERE DeleteMark != 1
AND PaymentStatusID IN (1,2)
ORDER BY DateOfCreation) as p
I'm assuming that tblPayments has a primary key column ID. If it is true, you can use this statment:
FROM tblBookings b
INNER JOIN tblPayments p ON p.ID = (
SELECT TOP 1 ID
FROM tblPayments
WHERE BookingID = b.BookingID
AND DeleteMark != 1
AND PaymentStatusID IN (1,2)
ORDER BY DateOfCreation)

Two If selection while a select query

SELECT o.id, o.id as oid, o.id as orderId, o.cid, o.date, o.state,
o.price, o.currency, o.lastChange, o.url AS permalink, o.period,
o.bloggerId, o.bloggerShare, o.offerValidity, o.rebate, o.cid,
o.reason, o.bidReason, o.bidDate, o.bidPeriod, o.rate,
o.lastChange2, o.permalinkDate, o.cancelDate, o.bidValidDate,
o.acceptDate, o.approveDate, o.archived, o.bloggerPrice,
o.customerPrice, o.cancelReason, o.listPrice, o.adFormat,
o.lastPayDate, o.startDate, o.endDate, o.customerBidDate,
o.zoneId, c.campaignStartDate, c.campaignEndDate,
c.type as campaignType, c.test, c.test1, c.special, c.packageId,
c.fixPrice, c.type, c.priceBidding, c.textCreation, o.hiddenField,
o.startDate, p.url as producturlold, p.pressurl, p.companyurl,
p.blogurl, p.mediaurl, p.short,
p.description as productDescription, p.description2, p.image,
c.teaser, c.kind, c.title, mc.country as campaignCountry,
c.minlen, c.productPrice, c.currency as campaignCurrency,
c.productTitle, c.url, c.producturl, c.pressurl, c.companyurl,
c.blogurl, c.mediaurl, c.description, c.image, c.teaser,
c.productReturn, c.testProduct, c.mid as customerId, c.adText,
c.fixAdText, c.requiresBlog, c.bidStop, c.accountingPeriod,
c.actionCodeType, c.actionCodesDescription, ac.code,
ac2.code as massCode, b.title as blogtitle, b.url as bloggerurl,
b.pis as pis, b.uniqueVisitors as uvs, b.pisCounter as pisCounter,
b.uvsCounter as uvsCounter, b.aPI as aPI, b.aUV as aUV,
b.id as blogId, p.title as productTitleOld,
b.lastChange as blogLastChange, b.trRank, r1.rate as orderRate,
r2.Rate as memberRate, b.reviews
FROM rates r1, rates r2, orders o
left join blog b on (o.blogId = b.id)
left join codes ac on (ac.orderId = o.id), campaign c
left join product p on (c.productId = p.id)
left join codes ac2 on (ac2.campaignId = c.id and
c.actionCodeType = 2),
person mc
where o.cid = c.id
and mc.mid = c.mid
and o.id = '223704'
and o.state <> 0
and r1.currency = o.currency
and r2.currency = 'EUR'
and r1.date = FROM_UNIXTIME(o.date, '%Y-%m-%d')
and r2.date = r1.date
I wnat to test if memberRate and orderRate is Null it should continue how can i do that? Any idea?
Tack this on the end should do the trick:
--Within the WHERE clause
AND r2.Rate IS NOT NULL
AND r1.Rate IS NOT NULL
I'm not sure I understand what you are asking, but add and memberRate is not null and orderRate is not null to the end of your query and you will skip all results where either of those two fields are null.