invoice table
SELECT id, fname, gtotal, `date` FROM invoice WHERE id = 1;
| id | fname | gtotal | date |
|----|---------|--------|-----------------------|
| 1 | Brandon | 860 | May, 11 2016 00:00:00 |
invoice_contents table,
SELECT * FROM invoice_contents WHERE invoice_id = 1;
| id | invoice_id | item | price | quantity | discount | total |
|----|------------|------------|-------|----------|----------|-------|
| 1 | 1 | Dextrose | 10 | 10 | 5 | 95 |
| 2 | 1 | Nescaine | 20 | 30 | 10 | 540 |
| 3 | 1 | Anticavity | 30 | 10 | 25 | 225 |
This JOIN query
SELECT invoice.id, invoice.fname, invoice_contents.item,
invoice_contents.price, invoice_contents.quantit,
invoice_contents.discount, invoice_contents.total,
invoice.gtotal
FROM invoice_contents
INNER JOIN invoice ON invoice_contents.invoice_id=1 AND invoice.id=1;
gives this result.
| id | fname | item | price | quantity | discount | total | gtotal |
|----|---------|------------|-------|----------|----------|-------|--------|
| 1 | Brandon | Dextrose | 10 | 10 | 5 | 95 | 860 |
| 1 | Brandon | Nescaine | 20 | 30 | 10 | 540 | 860 |
| 1 | Brandon | Anticavity | 30 | 10 | 25 | 225 | 860 |
I need this result.
| id | fname | item | price | quantity | discount | total | gtotal |
|----|---------|------------|-------|----------|----------|-------|--------|
| 1 | Brandon | Dextrose | 10 | 10 | 5 | 95 | 860 |
| | | Nescaine | 20 | 30 | 10 | 540 | |
| | | Anticavity | 30 | 10 | 25 | 225 | |
I am just a beginner in MySQL. I have been trying from this morning to get this kind of output by experimenting on different combinations please help me out.
#Rex, Your select is correct. You should make desired output using some script e.g. PHP.
try this in SQL:
in this Query i save everytime fname in a variable is not equal and at the next row i compare it and return a empty string is it equal. and the same for gtotal.
the cross join is only to initialize the variables.
in this case it is important that the rows are order by fname to ensure that the same name is behind each other
SELECT
invoice.id,
IF(#last_fname = invoice.fname, '', (#last_fname:=invoice.fname)) as fname,
invoice_contents.item,
invoice_contents.price,
invoice_contents.quantity,
invoice_contents.discount,
IF(#last_gtotal = invoice.gtotal, '', (#last_gtotal:=invoice.gtotal)) as gtotal
FROM invoice_contents
INNER JOIN invoice ON invoice_contents.invoice_id=1 AND invoice.id=1
CROSS JOIN ( select #last_fname := '' , #last_gtotal := '' ) AS parameter
ORDER BY invoice.fname;
Sample
MariaDB [bb]> SELECT
-> invoice.id,
-> IF(#last_fname = invoice.fname, '', (#last_fname:=invoice.fname)) AS fname,
-> invoice_contents.item,
-> invoice_contents.price,
-> invoice_contents.quantity,
-> invoice_contents.discount,
-> IF(#last_gtotal = invoice.gtotal, '', (#last_gtotal:=invoice.gtotal)) AS gtotal
-> FROM invoice_contents
-> INNER JOIN invoice ON invoice_contents.invoice_id=1 AND invoice.id=1
-> CROSS JOIN ( SELECT #last_fname:='' , #last_gtotal:='' ) AS parameter
-> ORDER BY invoice.fname;
+----+---------+------------+-------+----------+----------+--------+
| id | fname | item | price | quantity | discount | gtotal |
+----+---------+------------+-------+----------+----------+--------+
| 1 | Brandon | Dextrose | 10.00 | 10 | 5.00 | 860.00 |
| 1 | | Nescaine | 20.00 | 30 | 10.00 | |
| 1 | | Anticavity | 30.00 | 10 | 25.00 | |
+----+---------+------------+-------+----------+----------+--------+
3 rows in set, 1 warning (0.00 sec)
MariaDB [bb]>
Related
I came across this SQL at work, This was written by my colleague. Although there are better solutions, I’m just curious,and now I have simplified it as follows:
-- Calculate the total of the 'APPROVING' salary and the 'AGENT' salary already actual paid
SELECT ifnull(sum(l.salary),0) +
(SELECT ifnull(sum(l1.salary),0)
FROM salary_header h1 JOIN salary_lines l1
ON h1.salary_id = l1.salary_id
WHERE h1.status='APPROVING' AND l1.project_id = l.project_id)
FROM salary_pay_headers h JOIN salary_pay_lines l
ON h.salary_pay_id = l.salary_pay_id
WHERE h.pay_type='AGENT'
AND l.project_id=9904
mysql> select * from salary_header;
+-----------+-----------+
| salary_id | status |
+-----------+-----------+
| 1 | APPROVING |
| 2 | PAID |
+-----------+-----------+
mysql> select * from salary_lines;
+----------------+-----------+------------+--------+
| salary_line_id | salary_id | project_id | salary |
+----------------+-----------+------------+--------+
| 1 | 2 | 9905 | 200.00 |
+----------------+-----------+------------+--------+
mysql> select * from salary_pay_headers;
+---------------+----------+
| salary_pay_id | pay_type |
+---------------+----------+
| 1 | AGENT |
| 2 | OTHER |
+---------------+----------+
mysql> select * from salary_pay_lines;
+--------------------+---------------+------------+--------+
| salary_pay_line_id | salary_pay_id | project_id | salary |
+--------------------+---------------+------------+--------+
| 1 | 1 | 9904 | 3.05 |
| 2 | 1 | 9904 | 201.37 |
| 3 | 1 | 9904 | 6.10 |
| 4 | 1 | 9904 | 10.17 |
| 5 | 1 | 9904 | 6.44 |
| 6 | 1 | 9904 | 9.15 |
| 8 | 3 | 9905 | 100.00 |
+--------------------+---------------+------------+--------+
Its result is not 3.05+201.37+6.10+10.17+6.44+9.15=236.28 as I expected,but 236.28+200=436.28,obviously that one in the salary_line is not filtered out. I have spent the whole afternoon on this problem, so I really want to know the execution order of this SQL.
Sample data:
db1.locationDetails table
| id | locationUID | locationName |
|----|-------------|--------------|
| 1 | L0001 | Site A |
| 2 | L0002 | Site B |
| 3 | L0003 | Site C |
| 3 | L0004 | Site D |
db2.HealthData table
| id | locationID | Date_Time | memUsage |
|----|-------------|------------------|----------|
| 1 | L0001 | 2018-09-10 11:43 | 35 |
| 2 | L0002 | 2018-09-10 08:22 | 39 |
| 3 | L0003 | 2018-09-10 14:44 | 43 |
| 4 | L0004 | 2018-09-10 16:01 | 72 |
| 5 | L0001 | 2018-09-12 01:26 | 50 |
| 6 | L0002 | 2018-09-12 03:15 | 32 |
I have a query:
SELECT DISTINCT db1.locationDetails.locationUID,
db1.locationDetails.locationName,
MAX(db2.HealthData.Date_Time),
db2.HealthData.memUsage,
IF(DATE(db2.HealthData.Date_Time) = '2018-09-12', "ON", "OFF") AS Status
FROM db1.locationDetails
LEFT JOIN db2.HealthData
ON db1.locationDetails.locationUID = db2.HealthData.locationID
GROUP BY db1.locationDetails.locationUID
Based on my understanding, the 'Status' column will show "ON" if the Date is equals to 2018-09-12 but somehow it always returns "OFF" regardless of whether the value in the Date_Time column is equal to the Date value specified in the query.
Can anyone tell me what is wrong here? Thanks in advance.
Expected output:
| locationUID | locationName | Date_Time | memUsage | Status |
|-------------|--------------|-----------------|----------|--------|
| L0001 | Site A |2018-09-12 01:26 | 50 | ON |
| L0002 | Site B |2018-09-12 03:15 | 32 | ON |
| L0003 | Site C |2018-09-10 14:44 | 43 | OFF |
| L0004 | Site D |2018-09-10 16:01 | 72 | OFF |
Use subquery to get your desired result:
select x.locationuid,x.locationname,maxitme, memusage, case when date(maxtime)='2018-09-12' then 'ON' else 'OFF' end as status
from db1.locationDetails x
inner join
(select a.locationuid,maxtime,memusage
from
(SELECT locationUID,MAX(Date_Time) as maxtime FROM db2.HealthData group by locationUID)a
inner join db2.HealthData b on a.locationuid=b.locationuid)y
on x.locationuid=y.locationuid
add Group by db1.locationDetails.locationUID,db2.HealthData.id
SELECT DISTINCT db1.locationDetails.locationUID,
db1.locationDetails.locationName,
MAX(db2.HealthData.Date_Time),
db2.HealthData.memUsage,
IF(DATE(db2.HealthData.Date_Time) = '2018-09-12', "ON", "OFF") AS Status
FROM db1.locationDetails
LEFT JOIN db2.HealthData
ON db1.locationDetails.locationUID = db2.HealthData.locationID
GROUP BY db1.locationDetails.locationUID,db2.HealthData.id
my tables and their layout:
mysql> select * FROM xt_shipping_zones;
+---------+-------------+---------------------------------------------------------------------------+
| zone_id | zone_name | zone_countries |
+---------+-------------+---------------------------------------------------------------------------+
| 5 | ZONE1 | AT,BE,BG,DK,FI,FR,GR,IE,IT,LV,LT,LU,MC,NL,PL,PT,RO,SM,SE,SK,SI,ES,HU,GB |
| 6 | Deutschland | DE |
| 8 | ZONE2Brutto | AD,NO,VA |
| 9 | ZONE2NETTO | CH,LI |
+---------+-------------+---------------------------------------------------------------------------+
mysql> select * FROM xt_shipping_cost WHERE shipping_geo_zone = 99995 LIMIT 5;
+------------------+-------------+-------------------+-----------------------+--------------------------+------------------------+----------------+------------------+
| shipping_cost_id | shipping_id | shipping_geo_zone | shipping_country_code | shipping_type_value_from | shipping_type_value_to | shipping_price | shipping_allowed |
+------------------+-------------+-------------------+-----------------------+--------------------------+------------------------+----------------+------------------+
| 269 | 34 | 99995 | | 0.31 | 17.99 | 17.0000 | 1 |
| 270 | 34 | 99995 | | 17.99 | 35.99 | 34.0000 | 1 |
| 271 | 34 | 99995 | | 35.99 | 53.99 | 51.0000 | 1 |
| 272 | 34 | 99995 | | 53.99 | 71.99 | 68.0000 | 1 |
| 273 | 34 | 99995 | | 71.99 | 89.99 | 85.0000 | 1 |
+------------------+-------------+-------------------+-----------------------+--------------------------+------------------------+----------------+------------------+
mysql> SELECT * FROM geoip WHERE 92569600 BETWEEN start AND end;
+----------+----------+---------+-----+
| start | end | country | id |
+----------+----------+---------+-----+
| 92569600 | 92585983 | AT | 895 |
+----------+----------+---------+-----+
My Query:
SELECT
xt_shipping_cost.shipping_type_value_from,
xt_shipping_cost.shipping_type_value_to,
xt_shipping_cost.shipping_price,
geoip.country
FROM xt_shipping_cost
INNER JOIN xt_shipping_zones
ON xt_shipping_cost.shipping_geo_zone = xt_shipping_zones.zone_id + 99990
INNER JOIN geoip
ON geoip.country REGEXP xt_shipping_zones.zone_countries
WHERE 34664448 BETWEEN geoip.start AND geoip.end
My Problem:
Query is working if there is only ONE entry in xt_shipping_zones.zone_countries like DE. If there are multiple (with comma seperated entries) i cant get a match on that row.
Doing it manually:
mysql> SELECT * FROM `xt_shipping_zones` WHERE `zone_countries` REGEXP 'AT';
+---------+-----------+---------------------------------------------------------------------------+
| zone_id | zone_name | zone_countries |
+---------+-----------+---------------------------------------------------------------------------+
| 5 | ZONE1 | AT,BE,BG,DK,FI,FR,GR,IE,IT,LV,LT,LU,MC,NL,PL,PT,RO,SM,SE,SK,SI,ES,HU,GB |
+---------+-----------+---------------------------------------------------------------------------+
SQLFiddle: http://sqlfiddle.com/#!9/68f8d0/1
I hope i didn't failed to much to make my problem clear.
Thank you
I think you can use find_in_set()
SELECT
xt_shipping_cost.shipping_type_value_from,
xt_shipping_cost.shipping_type_value_to,
xt_shipping_cost.shipping_price,
geoip.country
FROM xt_shipping_cost
INNER JOIN xt_shipping_zones
ON xt_shipping_cost.shipping_geo_zone = xt_shipping_zones.zone_id + 99990
INNER JOIN geoip
ON find_in_set(geoip.country, xt_shipping_zones.zone_countries)
WHERE 34664448 BETWEEN geoip.start AND geoip.end
It is no good idea to store the values as csv. That is very bad database design.
What I have until now: http://sqlfiddle.com/#!2/bbfec/6
I want to get the quanity of shares for a given stock, that a given company has available to sell - grouped by price. For example, for company number 9 and stock number 1, I want the data like this:
| id | name | price | date | quantity | total |
------------------------------------------------------------------
| 3 | ALTR | 2.240 | 2015-05-12 04:29:29 | 50 | 112.00 |
| 7 | ALTR | 2.449 | 2014-06-10 18:21:02 | 50 | 122.45 |
Because company 9 bought 200 stocks on 2015-05-12 04:29:29, sold 100 on 2014-06-10 15:50:17, more 50 on 2014-06-10 17:06:18 and bought 50 on 2014-06-10 18:21:02.
I don't want the total of all shares, because they have different prices when a company acquires them. The price and the date are the purchasing price and date but the quantity is what is left from a certain purchasing.
Thanks in advance.
Strawberry, the desired result:
| id | price | date | quantity |
-----------------------------------------------
| 3 | 2.240 | 12-05-2015 | 50 |
| 7 | 2.449 | 10-06-2014 | 50 |
Start with:
select id_acao, id_empresa, ifnull(bought,0) - ifnull(sold,0) as stock
from
(
select id_acao, id_empresa,
(select sum(quantidade) from acao_trans where tipo='C' and id_acao=a.id_acao and id_empresa=a.id_empresa) as bought,
(select sum(quantidade) from acao_trans where tipo='V' and id_acao=a.id_acao and id_empresa=a.id_empresa) as sold
from acao_trans a group by id_acao,id_empresa
) x
;
+---------+------------+-------+
| id_acao | id_empresa | stock |
+---------+------------+-------+
| 1 | 4 | 1500 |
| 1 | 9 | 100 |
| 8 | 9 | 3500 |
| 13 | 9 | 5000 |
+---------+------------+-------+
And join this query to your base acao and empresa tables.
Remark: For statistics etc. it would be easier to use negative quantities for selling transactions instead of a transaction type 'C' and 'V'.
For ease of (my) comprehension, I translated and adjusted your stock table slightly...
SELECT a.stock_id
, a.company_id
, a.transaction_date
, a.price
, COALESCE(a.quantity - SUM(b.quantity),a.quantity) quantity
, COALESCE(a.quantity - SUM(b.quantity),a.quantity) * a.price subtotal
FROM stock_company a
LEFT
JOIN
( SELECT x.stock_id
, x.company_id
, MAX(x.transaction_date) min_transaction_date
, y.quantity
FROM stock_company x
JOIN stock_company y
ON y.stock_id = x.stock_id
AND y.company_id = x.company_id
AND y.transaction_date <= x.transaction_date
AND y.transaction_type <> x.transaction_type
WHERE y.transaction_type = 'SELL'
GROUP
BY x.stock_id
, x.company_id
, y.quantity
) b
ON b.stock_id = a.stock_id
AND b.company_id = a.company_id
AND b.min_transaction_date = a.transaction_date
WHERE a.stock_id = 1
AND a.company_id = 9
AND a.transaction_type = 'BUY'
GROUP
BY stock_id
, company_id
, transaction_date;
+----------+------------+---------------------+-------+----------+----------+
| stock_id | company_id | transaction_date | price | quantity | subtotal |
+----------+------------+---------------------+-------+----------+----------+
| 1 | 9 | 2014-06-10 18:21:02 | 2.449 | 50 | 122.450 |
| 1 | 9 | 2015-05-12 04:29:29 | 2.240 | 50 | 112.000 |
+----------+------------+---------------------+-------+----------+----------+
http://www.sqlfiddle.com/#!2/cfa4d/1
Note that this hasn't been tested extensively so there may be a flaw (or perhaps several flaws!) in my logic, but it seems to work well enough on the data set provided.
EDIT: I made a slight adjustment - still not sure if it's enough. Let me know.
Maybe now I've understood it. How about this:
select c.id,c.id_empresa,c.id_acao,c.data as c_data,c.quantidade as c_quantidade,v.preco,v.id as v_id,v.data as v_data,ifnull(v.quantidade,0) as v_quantidade, c.preco*v.quantidade as bought, v.preco*v.quantidade as sold
from acao_trans c
left join acao_trans v
on c.id=v.parent
order by id_empresa, id_acao,c_data,v_data
which results in
+----+------------+---------+---------------------+--------------+-------+------+---------------------+--------------+----------+----------+
| id | id_empresa | id_acao | c_data | c_quantidade | preco | v_id | v_data | v_quantidade | bought | sold |
+----+------------+---------+---------------------+--------------+-------+------+---------------------+--------------+----------+----------+
| 4 | 4 | 1 | 2014-06-10 08:59:09 | 2000 | 2.385 | 8 | 2014-06-11 10:39:48 | 500 | 1184.000 | 1192.500 |
| 8 | 4 | 1 | 2014-06-11 10:39:48 | 500 | NULL | NULL | NULL | 0 | NULL | NULL |
| 5 | 9 | 1 | 2014-06-10 15:50:17 | 100 | NULL | NULL | NULL | 0 | NULL | NULL |
| 6 | 9 | 1 | 2014-06-10 17:06:18 | 50 | NULL | NULL | NULL | 0 | NULL | NULL |
| 7 | 9 | 1 | 2014-06-10 18:21:02 | 50 | NULL | NULL | NULL | 0 | NULL | NULL |
| 3 | 9 | 1 | 2015-05-12 04:29:29 | 200 | 2.430 | 5 | 2014-06-10 15:50:17 | 100 | 224.000 | 243.000 |
| 3 | 9 | 1 | 2015-05-12 04:29:29 | 200 | 2.449 | 6 | 2014-06-10 17:06:18 | 50 | 112.000 | 122.450 |
| 2 | 9 | 8 | 2015-05-12 04:27:56 | 3500 | NULL | NULL | NULL | 0 | NULL | NULL |
| 1 | 9 | 13 | 2015-05-12 04:25:52 | 5000 | NULL | NULL | NULL | 0 | NULL | NULL |
+----+------------+---------+---------------------+--------------+-------+------+---------------------+--------------+----------+----------+
Can you go on from there?
Ok, now I think I got it.
Here's the query resulting what I wanted:
SELECT p.id
, a.nome
, p.preco
, date_format(p.`data`,'%m/%d/%Y') AS `data`
, COALESCE(p.quantidade-SUM(f.quantidade), p.quantidade) AS quantidade
, p.preco*COALESCE(p.quantidade-SUM(f.quantidade), p.quantidade) AS total
FROM acao_trans p
LEFT JOIN acao_trans f
ON p.id=f.parent
INNER JOIN acao a
ON p.id_acao=a.id
WHERE p.parent IS NULL
AND p.id_acao=1
AND p.id_empresa=9
GROUP BY p.id
Fiddle: http://sqlfiddle.com/#!2/bbfec/64.
What I did: I joined the table that matters (acao_trans "p") with itself ("f") and I used Sum function to aggregate all the quantities of second argument, giving me the total of all sold shares. If there are records on "f" I want to subtract that total of the quantity of purchasing shares ("p"). If there is not a correspondence it will show null fields and I show purchased quantity. After it's done it's kind of simple. Quantity was what really mattered here, with that I was able to reach other things easily.
I am trying to show delivery charges for a shop I am building, there are three tables in the database 1 for the service ie Royal Mail, Carrier..., one for the band ie. UK, Europe, Worldwide1 etc.. and one for the charges (qty = weight)
I have a database of three tables that, when joined form the following
+------------------+-----+-----------+-------+---------+---------------+----------+-------+-------------+
| name | qty | serviceID | basis | bandID | initial_charge | chargeID | price | total_price |
+------------------+-----+-----------+-------+---------+---------------+----------+-------+-------------+
| Collect in store | 0 | 3 | | 1 | 3 | 0.00 | 2 | 0.00 |
| Royal mail | 0 | 1 | 2 | 4 | 2.00 | 3 | 0.00 | 2.00 |
| Royal mail | 1 | 1 | 2 | 4 | 2.00 | 4 | 1.00 | 3.00 |
| APC | 0 | 2 | 1 | 1 | 0.00 | 6 | 5.95 | 5.95 |
+------------------+-----+-----------+-------+---------+---------------+----------+-------+-------------+
Basically what I want to do is (as you can see) Royal Mail has two entries as there are more than one entry in the joined table. What I would like to do is show the highest of the two royal mail entries (I was initially trying to group by service_id) whilst also maintaining the two other services with different service id's
Any assistance would be great as this is driving me mad. I feel like I have tried every combination going!
In the example below the qty (weight) of the items is 3kg
SELECT
`service`.`name`,
`charge`.`qty`,
`service`.`serviceID`,
`band`.`bandID`,
`band`.`initial_charge`,
`charge`.`chargeID`,
`charge`.`price`,
`band`.`initial_charge` + `charge`.`price` AS `total_price`
FROM
`delivery_band` AS `band`
LEFT JOIN
`delivery_charge` AS `charge`
ON
`charge`.`bandID` = `band`.`bandID`
AND
`charge`.`qty` < '3'
LEFT JOIN
`delivery_service` AS `service`
ON
`service`.`serviceID` = `band`.`serviceID`
WHERE
FIND_IN_SET( '225', `band`.`accepted_countries` )
AND
(
`band`.`min_qty` >= '3'
OR
`band`.`min_qty` = '0'
)
AND
(
`band`.`max_qty` <= '3'
OR
`band`.`max_qty` = '0'
)
delivery_service
+-----------+------------------+
| serviceID | name |
+-----------+------------------+
| 1 | Royal mail |
| 2 | APC |
| 3 | Collect in store |
+-----------+------------------+
delivery_band
+--------+-----------+-----------------+----------------+---------+---------+-------------------------------------------------------+
| bandID | serviceID | name | initial_charge | min_qty | max_qty | accepted_countries |
+--------+-----------+-----------------+----------------+---------+---------+-------------------------------------------------------+
| 1 | 2 | UK Mainland | 0.00 | 0 | 0 | 225 |
| 2 | 2 | UK Offshore | 14.00 | 0 | 0 | 240 |
| 3 | 3 | Bradford Store | 0.00 | 0 | 0 | 225 |
| 4 | 1 | UK | 2.00 | 0 | 0 | 225 |
| 5 | 2 | World wide | 15.00 | 0 | 0 | 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20... |
| 6 | 1 | World wide Mail | 5.00 | 0 | 0 | 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20... |
+--------+-----------+-----------------+----------------+---------+---------+-------------------------------------------------------+
delivery_charge
+----------+--------+-----+-------+
| chargeID | bandID | qty | price |
+----------+--------+-----+-------+
| 1 | 2 | 0 | 5.00 |
| 2 | 3 | 0 | 0.00 |
| 3 | 4 | 0 | 0.00 |
| 4 | 4 | 1 | 1.00 |
| 5 | 4 | 5 | 3.00 |
| 6 | 1 | 0 | 5.95 |
| 7 | 1 | 10 | 10.95 |
| 8 | 2 | 10 | 14.00 |
| 9 | 5 | 0 | 0.00 |
| 10 | 5 | 3 | 5.00 |
| 11 | 5 | 6 | 10.00 |
| 12 | 5 | 9 | 15.00 |
| 13 | 6 | 0 | 0.00 |
| 14 | 6 | 2 | 5.00 |
| 15 | 6 | 4 | 10.00 |
| 16 | 6 | 6 | 15.00 |
+----------+--------+-----+-------+
When I tried adding the charge table as a sub query and then limiting that query it gave me NULL's for all the charge table fields
If I try the following query:
SELECT
`service`.`name`,
`charge`.`qty`,
`service`.`serviceID`,
`band`.`bandID`,
`band`.`initial_charge`,
`charge`.`chargeID`,
MAX( `charge`.`price` ) AS `price`,
`band`.`initial_charge` + `charge`.`price` AS `total_price`
FROM
`delivery_band` AS `band`
LEFT JOIN
`delivery_charge` AS `charge`
ON
`charge`.`bandID` = `band`.`bandID`
AND
`charge`.`qty` < '3'
LEFT JOIN
`delivery_service` AS `service`
ON
`service`.`serviceID` = `band`.`serviceID`
WHERE
FIND_IN_SET( '225', `band`.`accepted_countries` )
AND
(
`band`.`min_qty` >= '3'
OR
`band`.`min_qty` = '0'
)
AND
(
`band`.`max_qty` <= '3'
OR
`band`.`max_qty` = '0'
)
GROUP BY
`service`.`serviceID`
I get this returned:
+------------------+-----+-----------+--------+----------------+----------+-------+-------------+
| name | qty | serviceID | bandID | initial_charge | chargeID | price | total_price |
+------------------+-----+-----------+--------+----------------+----------+-------+-------------+
| Royal mail | 0 | 1 | 4 | 2.00 | 3 | 1.00 | 2.00 |
| APC | 0 | 2 | 1 | 0.00 | 6 | 5.95 | 5.95 |
| Collect in store | 0 | 3 | 3 | 0.00 | 2 | 0.00 | 0.00 |
+------------------+-----+-----------+--------+----------------+----------+-------+-------------+
Which looks fine in principle until you realise that the chargeID = 3 has a price of 0.00 and yet the table is showing a price of 1.00 so the values seem to have become disassociated
What I would like to do is show the highest of the two royal mail entries
You can use MAX to obtain the maximum of a given column, e.g.
SELECT … MAX(charge.price) … FROM …
If you absolutely need the other columns (like charge.chargeID) to match, things will become a lot more complicated. So make sure you actually need that. For details on the general idea behind this kind of query, have a closer look at Select one value from a group based on order from other columns. Adapting this answer by #RichardTheKiwi, I came up with the following query:
SELECT s.name,
c.qty,
s.serviceID,
b.bandID,
b.initial_charge,
c.chargeID,
c.price,
b.initial_charge + c.price AS total_price
FROM delivery_band AS b,
delivery_service AS s,
(SELECT chargeID, price, qty,
#rowctr := IF(bandId = #lastBand, #rowctr+1, 1) AS rowNumber,
#lastBand := bandId AS bandId
FROM (SELECT #rowctr:=0, #lastBand:=null) init,
delivery_charge
WHERE qty < 3
ORDER BY bandId, price DESC
) AS c
WHERE FIND_IN_SET(225, b.accepted_countries)
AND (b.min_qty >= 3 OR B.min_qty = 0)
AND (b.max_qty <= 3 OR B.max_qty = 0)
AND s.serviceID = b.serviceID
AND c.bandID = b.bandID
AND c.rowNumber = 1
See this fiddle for the corresponding output. Note that I only do inner queries, not left queries, since that seems sufficient for the query in question, and keeps things a lot more readable so you can concentrate on the important parts, i.e. those involving rowNumber. The idea is that the subquery generates row numbers for the items of the same band, resetting them for the next band. When you select only rows with rowNumber being 1, you only get the highest price, with all other columns associated with that.