I have this table :
CREATE TABLE [BGIA].[INTCOL004VA](
[ID] [int] NOT NULL,
[DATYEN] [varchar](18) NULL,
[ZZRIDN] [varchar](8) NULL,
[OQTIEF] [varchar](1) NULL,
[OQMONE] [varchar](3) NULL,
[ZZPONR] [varchar](3) NULL,
[ZZNBRE] [varchar](15) NULL,
[ZZPDSE] [varchar](22) NULL
);
INSERT INTO INTCOL004VA VALUES
('53671955', 'MC1141103006', '38565363', '1', '007', '010', '0', '0'),
('53671956', 'MC1141103006', '38565363', '0', NULL, '020', '0', '0'),
('53671957', 'MC1141103006', '38565363', '0', '007', '030', '1', '500'),
('53671958', 'VT1141103010', '38565421', '1', '007', '050', '0', '0'),
('53671959', 'VT1141103010', '38565421', '0', NULL, '100', '0', '0'),
('53671960', 'ST1141103006', '38587542', '0', NULL, '010', '1', '500'),
('53671961', 'ST1141103006', '38587542', '1', 'B01', '020', '5', '0');
Records are linked by DATYEN, ZZRIDN and ZZPONR
I want update table with this rule :
For one link DATYEN, ZZRIDN if one row are not 0 on ZZNBRE and ZZPDSE => OQTIEF = 0 and OQMONE = NULL
But for one link DATYNE, ZZRIDN if all rows ar 0 on ZZNBRE and ZZPDSE and one row have OQTIEF = 1 and OQMONE not null => apply on all row af link OQTIEF = 1 and OQMONE = OQMONE of not null row
I can not do with an INNER JOIN and suddenly I do not know how to succeed
Thank you :)
Edit : For exemple, this :
('53671955', 'MC1141103006', '38565363', '1', '007', '010', '0', '0'),
('53671956', 'MC1141103006', '38565363', '0', NULL, '020', '0', '0'),
('53671957', 'MC1141103006', '38565363', '0', '007', '030', '1', '500')
Must be :
('53671955', 'MC1141103006', '38565363', '0', NULL, '010', '0', '0'),
('53671956', 'MC1141103006', '38565363', '0', NULL, '020', '0', '0'),
('53671957', 'MC1141103006', '38565363', '0', NULL, '030', '1', '500')
Because group MC1141103006 and 38565363 have one row with ZZNBRE and ZZPDSE not 0
This :
('53671960', 'ST1141103006', '38587542', '0', NULL, '010', '1', '500'),
('53671961', 'ST1141103006', '38587542', '1', 'B01', '020', '5', '0')
Must be :
('53671960', 'ST1141103006', '38587542', '0', NULL, '010', '1', '500'),
('53671961', 'ST1141103006', '38587542', '0', NULL, '020', '0', '0')
Because group ST1141103006 and 38587542 have one row with ZZNBRE and ZZPDSE not 0 but set ZZNBRE to 0 because ZZPDSE is 0
And this :
('53671958', 'VT1141103010', '38565421', '1', '007', '050', '0', '0'),
('53671959', 'VT1141103010', '38565421', '0', NULL, '100', '0', '0')
Must be :
('53671958', 'VT1141103010', '38565421', '1', '007', '050', '0', '0'),
('53671959', 'VT1141103010', '38565421', '1', '007', '100', '0', '0')
Because all row have ZZNBRE and ZZNBRE are 0
I hope to be precise, it is not easy to understand I guess :(
Edit 2 : Actually my query is :
update v1
set v1.zznbre = (case when v1.zzpdse = 0 then 0 else v1.zznbre end),
v1.oqtief = (case when v1.zznbre = 0 and v2.zznbre = 0 and v1.zzpdse = 0 and v2.zzpdse = 0 then 1 else 0 end),
v1.oqmone = (case when v1.zznbre = 0 and v2.zznbre = 0 and v1.zzpdse = 0 and v2.zzpdse = 0 then v2.oqmone else null end)
from intcol004va v1
inner join intcol004va v2 on v2.datyen = v1.datyen and v2.zzridn = v1.zzridn and v2.id <> v1.id
where v2.oqtief = 1 and v2.oqmone is not null and v1.oqtief <> v2.oqtief
But not work correctly in all case :(
If you process the update as two independent updates it appears to generate the correct answer set.
I included a result table and code that will show a comparison between original data and the desired result table as defined from your description.
Next it will do the two updates and then show the joined original and goal tables to demonstrate that they are aligned correctly.
CREATE TABLE [INTCOL004VA](
[ID] [int] NOT NULL,
[DATYEN] [varchar](18) NULL,
[ZZRIDN] [varchar](8) NULL,
[OQTIEF] [varchar](1) NULL,
[OQMONE] [varchar](3) NULL,
[ZZPONR] [varchar](3) NULL,
[ZZNBRE] [varchar](15) NULL,
[ZZPDSE] [varchar](22) NULL
);
CREATE TABLE [R_INTCOL004VA](
[ID] [int] NOT NULL,
[DATYEN] [varchar](18) NULL,
[ZZRIDN] [varchar](8) NULL,
[OQTIEF] [varchar](1) NULL,
[OQMONE] [varchar](3) NULL,
[ZZPONR] [varchar](3) NULL,
[ZZNBRE] [varchar](15) NULL,
[ZZPDSE] [varchar](22) NULL
);
INSERT INTO INTCOL004VA VALUES
('53671955', 'MC1141103006', '38565363', '1', '007', '010', '0', '0'),
('53671956', 'MC1141103006', '38565363', '0', NULL, '020', '0', '0'),
('53671957', 'MC1141103006', '38565363', '0', '007', '030', '1', '500'),
('53671958', 'VT1141103010', '38565421', '1', '007', '050', '0', '0'),
('53671959', 'VT1141103010', '38565421', '0', NULL, '100', '0', '0'),
('53671960', 'ST1141103006', '38587542', '0', NULL, '010', '1', '500'),
('53671961', 'ST1141103006', '38587542', '1', 'B01', '020', '5', '0');
INSERT INTO [R_INTCOL004VA] VALUES
('53671955', 'MC1141103006', '38565363', '0', NULL, '010', '0', '0'),
('53671956', 'MC1141103006', '38565363', '0', NULL, '020', '0', '0'),
('53671957', 'MC1141103006', '38565363', '0', NULL, '030', '1', '500'),
('53671960', 'ST1141103006', '38587542', '0', NULL, '010', '1', '500'),
('53671961', 'ST1141103006', '38587542', '0', NULL, '020', '0', '0'),
('53671958', 'VT1141103010', '38565421', '1', '007', '050', '0', '0'),
('53671959', 'VT1141103010', '38565421', '1', '007', '100', '0', '0')
SELECT
D.ID,
D.DATYEN,
D.ZZRIDN,
D.OQTIEF,
E.OQTIEF AS CORRECT_OQTIEF,
D.OQMONE,
E.OQMONE AS CORRECT_OQMONE,
D.ZZPONR,
D.ZZNBRE,
D.ZZPDSE
FROM
INTCOL004VA AS D
INNER JOIN
R_INTCOL004VA AS E ON D.ID = E.ID
UPDATE
INTCOL004VA
SET
OQTIEF = 0,
OQMONE = NULL
FROM
INTCOL004VA AS A
INNER JOIN
(SELECT
B.DATYEN,
B.ZZRIDN
FROM
INTCOL004VA AS B
GROUP BY
B.DATYEN,
B.ZZRIDN
HAVING
SUM(CAST(B.ZZNBRE AS INT)) > 0
) AS C ON A.DATYEN = C.DATYEN AND A.ZZRIDN = C.ZZRIDN
UPDATE
INTCOL004VA
SET
OQTIEF = 1,
OQMONE = C.OQMONE
FROM
INTCOL004VA AS A
INNER JOIN
(SELECT
B.DATYEN,
B.ZZRIDN,
MAX(ISNULL(B.OQMONE,'')) AS OQMONE
FROM
INTCOL004VA AS B
GROUP BY
B.DATYEN,
B.ZZRIDN
HAVING
SUM(CAST(B.OQTIEF AS INT)) > 0
) AS C ON A.DATYEN = C.DATYEN AND A.ZZRIDN = C.ZZRIDN
SELECT
D.ID,
D.DATYEN,
D.ZZRIDN,
D.OQTIEF,
E.OQTIEF AS CORRECT_OQTIEF,
D.OQMONE,
E.OQMONE AS CORRECT_OQMONE,
D.ZZPONR,
D.ZZNBRE,
D.ZZPDSE
FROM
INTCOL004VA AS D
INNER JOIN
R_INTCOL004VA AS E ON D.ID = E.ID
Sometimes just breaking it up into smaller pieces is the easier way to attack the problem.
Related
I'm calculating distance between people like below:
select (
point(
(select latlng from user_account where name = 'Manel')
)
<#>
point(
(select latlng from user_account where name = 'Ben')
)
) as distance
which will then output like this:
The scenario is that if Manel wants to get all the people within 5 km, how to write the SQL Query?
(We are using name as the input parameter and there is Latlng stored in the table the type is point)
Here is the sample data:
DROP TABLE IF EXISTS "user_account";
DROP SEQUENCE IF EXISTS user_account_id_seq;
CREATE SEQUENCE user_account_id_seq INCREMENT 1 MINVALUE 1 MAXVALUE 2147483647 START 1 CACHE 1;
CREATE TABLE "public"."user_account" (
"id" integer DEFAULT nextval('user_account_id_seq') NOT NULL,
"first_name" character varying(64) NOT NULL,
"last_name" character varying(64) NOT NULL,
"nickname" character varying(64),
"age" character varying(32),
"details" text,
"email" character varying(128),
"last_login_time" timestamp,
"create_time" timestamp,
"popularity" numeric(5,2),
"interested_in_relation" character varying(32),
"interested_in_gender" character varying(32),
"tag" character varying(256),
"point" integer,
"membership_type" character varying(32),
"account_status" character varying(32),
"account_name" character varying(32),
"password" character varying(32),
"latlng" point,
CONSTRAINT "user_account_ak_1" UNIQUE ("email"),
CONSTRAINT "user_account_pk" PRIMARY KEY ("id")
) WITH (oids = false);
INSERT INTO "user_account" ("id", "first_name", "last_name", "nickname", "age", "details", "email", "last_login_time", "create_time", "popularity", "interested_in_relation", "interested_in_gender", "tag", "point", "membership_type", "account_status", "account_name", "password", "latlng") VALUES
(8, 'Addison', 'Davies', 'Addison Davies', NULL, NULL, 'addison.davies#example.com', '2021-04-15 15:18:01.982', '2021-04-15 15:18:01.982', NULL, NULL, NULL, NULL, 0, 'normal', 'active', 'blackswan592', 'ajax', '(-0.1277,51.5073)'),
(10, 'Manel', 'Almeida', 'Manel Almeida', NULL, NULL, 'manel.almeida#example.com', '2021-04-15 15:28:25.85', '2021-04-15 15:28:25.85', NULL, NULL, NULL, NULL, 0, 'normal', 'active', 'orangekoala363', 'clarissa', '(-73.5959,-50.4127)'),
(11, 'Ben', 'Tidemann', 'Ben Tidemann', NULL, NULL, 'ben.tidemann#example.com', '2021-04-15 15:28:37.776', '2021-04-15 15:28:37.776', NULL, NULL, NULL, NULL, 0, 'normal', 'active', 'sadfrog539', 'morpheus', '(51.8397,-147.6034)'),
(12, 'Dieter', 'Campos', 'Dieter Campos', NULL, NULL, 'dieter.campos#example.com', '2021-04-15 15:28:38.939', '2021-04-15 15:28:38.939', NULL, NULL, NULL, NULL, 0, 'normal', 'active', 'silvercat262', 'irish', '(-72.8698,-139.8647)'),
(13, 'Girão', 'Martins', 'Girão Martins', NULL, NULL, 'girao.martins#example.com', '2021-04-15 15:33:58.464', '2021-04-15 15:33:58.464', NULL, NULL, NULL, NULL, 0, 'normal', 'active', 'yellowgoose254', 'shotgun', '(-69.7453,-170.808)'),
(14, 'Tammy', 'Hale', 'Tammy Hale', NULL, NULL, 'tammy.hale#example.com', '2021-04-15 15:33:59.925', '2021-04-15 15:33:59.925', NULL, NULL, NULL, NULL, 0, 'normal', 'active', 'beautifulzebra663', 'james007', '(25.8726,55.214)'),
(15, 'Hudson', 'Miller', 'Hudson Miller', NULL, NULL, 'hudson.miller#example.com', '2021-04-15 15:34:33.501', '2021-04-15 15:34:33.501', NULL, NULL, NULL, NULL, 0, 'normal', 'active', 'angrygorilla353', '414141', '(-59.3342,-90.5217)'),
(16, 'Apolline', 'Renard', 'Apolline Renard', NULL, NULL, 'apolline.renard#example.com', '2021-04-15 15:35:02.523', '2021-04-15 15:35:02.523', NULL, NULL, NULL, NULL, 0, 'normal', 'active', 'smallleopard612', '143143', '(0.6492,18.2443)'),
(17, 'Afet', 'Demirel', 'Afet Demirel', NULL, NULL, 'afet.demirel#example.com', '2021-04-15 15:35:08.072', '2021-04-15 15:35:08.072', NULL, NULL, NULL, NULL, 0, 'normal', 'active', 'happyfrog105', 'niners', '(75.6424,138.3762)'),
(18, 'Necati', 'Numanoğlu', 'Necati Numanoğlu', NULL, NULL, 'necati.numanoglu#example.com', '2021-04-15 15:35:09.242', '2021-04-15 15:35:09.242', NULL, NULL, NULL, NULL, 0, 'normal', 'active', 'bluefish441', 'beavis', '(70.8946,-7.5597)'),
(19, 'Danny', 'Soto', 'Danny Soto', NULL, NULL, 'danny.soto#example.com', '2021-04-15 15:35:10.32', '2021-04-15 15:35:10.32', NULL, NULL, NULL, NULL, 0, 'normal', 'active', 'blackpanda305', 'pentium', '(-79.9498,-171.0615)'),
(20, 'Jesse', 'Aro', 'Jesse Aro', NULL, NULL, 'jesse.aro#example.com', '2021-04-15 15:35:11.457', '2021-04-15 15:35:11.457', NULL, NULL, NULL, NULL, 0, 'normal', 'active', 'beautifulkoala522', 'lonely', '(-7.8552,-1.1386)'),
(21, 'Lucy', 'Zhang', 'Lucy Zhang', NULL, NULL, 'lucy.zhang#example.com', '2021-04-15 15:35:12.406', '2021-04-15 15:35:12.406', NULL, NULL, NULL, NULL, 0, 'normal', 'active', 'brownladybug716', 'beautiful', '(63.4473,52.2642)'),
(22, 'محیا', 'گلشن', 'محیا گلشن', NULL, NULL, 'mhy.glshn#example.com', '2021-04-15 15:35:13.503', '2021-04-15 15:35:13.503', NULL, NULL, NULL, NULL, 0, 'normal', 'active', 'browncat969', 'jorge', '(28.8925,109.2892)'),
(23, 'Jorge', 'Roman', 'Jorge Roman', NULL, NULL, 'jorge.roman#example.com', '2021-04-15 16:20:55.996', '2021-04-15 16:20:55.996', NULL, NULL, NULL, NULL, 0, 'normal', 'active', 'crazyostrich244', 'yyyyyyyy', '(-20.7278,-17.5191)'),
(24, 'Clayton', 'Jacobs', 'Clayton Jacobs', NULL, NULL, 'clayton.jacobs#example.com', '2021-04-15 16:20:57.276', '2021-04-15 16:20:57.276', NULL, NULL, NULL, NULL, 0, 'normal', 'active', 'happyrabbit978', 'killers', '(88.5666,-97.9353)');
Here is a query that returns all the people within a range of 5 km for a given name:
SELECT
ua1.id AS id1,
ua1.first_name AS name1,
ua1.latlng AS latlng1,
ua2.id AS id2,
ua2.first_name AS name2,
ua2.latlng AS latlng2,
(ua1.latlng <#> ua2.latlng) * 1.609344 as distance
FROM user_account ua1
JOIN user_account ua2 ON ua1.id <> ua2.id
WHERE ua1.first_name = 'Manel'
AND (ua1.latlng <#> ua2.latlng) * 1.609344 < 5;
Please note that the <#> operator returns miles instead of kilometers, so additional conversion is necessary, as shown above.
Thanks for Karol's nice answer! I also come up with a solution.
WITH latlng1 AS (
SELECT
latlng
FROM
user_account
WHERE
first_name = 'Manel'
),
result AS (
SELECT
(
point(
(latlng1.latlng)
) <#> point(
(user_account.latlng)
)
) as distance,
user_account.nickname
from
user_account,
latlng1
)
select
*
from
result
where
distance < 5 / 1.609344 AND nickname <> 'Manel Almeida'
I want to get the prices for each product for a specific place. Here's what I have done so far.
SELECT pl.id AS place_id,
pl.data_name AS place_name,
pp.data_price AS product_price,
pp.date_updated AS price_updated
FROM places AS pl
JOIN products AS pr
ON pl.id = pr.id_place
JOIN products_prices AS pp
WHERE pp.id_product = '30'
GROUP BY pl.id, pp.data_price, pp.date_updated
ORDER BY pp.data_price DESC, pp.date_updated DESC
As you can see from the image above, product_price and price_updated are all the same. place_name also shows 3 places that does not have the product with id 30.
Here's how it should looks like (cheapest, most recent product purchase on top):
place_id place_name product_price price_updated
3 ICA Maxi 4.95 2018-05-16
1 ICA Supermarket 5.90 2018-05-27
26 ICA Skutan 6.50 2018-05-29
Here's the database structure:
CREATE TABLE IF NOT EXISTS `places` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`data_name` tinytext NOT NULL,
`data_address` text,
`data_address_city` tinytext NOT NULL,
`data_coordinates` varchar(50) NOT NULL,
UNIQUE KEY `id` (`id`)
);
INSERT INTO `places` (`id`, `data_name`, `data_address`, `data_address_city`, `data_coordinates`) VALUES
(1, 'ICA Supermarket', 'Björkhagsgatan 9', 'Skoghall', '59.324971,13.467291'),
(2, 'ICA Maxi', 'Bergviks Köpcentrum', 'Karlstad', '59.376563,13.428787'),
(3, 'ICA Kvantum', 'Bivägen 11', 'Hammarö', '59.343388,13.504583'),
(4, 'IKEA', 'Bergviksvägen 43', 'Karlstad', '59.379032,13.420646'),
(5, 'Karlstad Naprapatklinik', 'Västra Torggatan 15', 'Karlstad', '59.381379,13.501683'),
(9, 'Besök i Borgvik AB', '', 'Borgvik', '59.348261,12.954707'),
(23, 'Mariebergsskogen', '', 'Karlstad', '59.369403,13.486485'),
(24, 'Happy Price', 'Brehogsvägen 20', 'Tanumshede', '58.723730,11.344768'),
(25, 'Trekanten Kök & Bar', 'Parkvägen 2', 'Hamburgsund', '58.552733,11.270998'),
(26, 'ICA Skutan', 'Strandvägen', 'Hamburgsund', '58.552122,11.270898');
CREATE TABLE IF NOT EXISTS `products` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_place` int(11) NOT NULL,
`data_barcode` text NOT NULL,
`data_name` text NOT NULL,
`data_weight` text NOT NULL,
`data_weight_type` text NOT NULL,
UNIQUE KEY `id` (`id`)
);
INSERT INTO `products` (`id`, `id_place`, `data_barcode`, `data_name`, `data_weight`, `data_weight_type`) VALUES
(7, 3, '7311070008494', 'Pågen Lantbröd', '650', 'g'),
(8, 3, '7310618084808', 'Grumme citronsåpa', '750', 'ml'),
(9, 3, '7318690079835', 'ICA Basic toalettpapper', '', ''),
(12, 1, '7318690134640', 'ICA Basic Milk & Caramel', '100', 'g'),
(18, 3, '7310380512103', 'ICA Home dishmatic refillsvamp', '', ''),
(19, 3, '7340109200684', 'Plastkasse', '', ''),
(20, 1, '7310751163903', 'ICA tonfisk filébitar i vatten', '185', 'g'),
(24, 1, '7310865001818', 'Arla mellanmjölk', '1.5', 'kg'),
(25, 1, '7318690079712', 'ICA kattsand (klumpbildande, ej parfym)', '6', 'kg'),
(29, 26, '3068320055008', 'Evian mineralvatten', '500', 'mL'),
(30, 26, '7318690134640', 'ICA Basic Milk & Caramel', '100', 'g'),
(33, 2, '0', 'ICA Basic Milk & Caramel', '100', 'g');
CREATE TABLE IF NOT EXISTS `products_prices` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_product` int(11) NOT NULL,
`id_transaction` int(11) NOT NULL,
`data_price` decimal(10,2) NOT NULL,
`data_amount` tinytext NOT NULL,
`data_discount` tinytext,
`data_discount_amount` tinytext,
`data_discount_sum` tinytext,
`data_pant` tinytext,
`date_updated` date NOT NULL,
UNIQUE KEY `id` (`id`)
);
INSERT INTO `products_prices` (`id`, `id_product`, `id_transaction`, `data_price`, `data_amount`, `data_discount`, `data_discount_amount`, `data_discount_sum`, `data_pant`, `date_updated`) VALUES
(1, 1, 907, 18.90, '4', '', '2', '30', NULL, '2018-05-18'),
(2, 12, 907, 4.90, '4', '', '', '', NULL, '2018-05-18'),
(5, 4, 904, 18.90, '1', '', '', '', NULL, '2018-05-18'),
(6, 14, 904, 14.90, '1', '', '', '', NULL, '2018-05-18'),
(17, 19, 936, 2.00, '1', '', '', '', NULL, '2018-05-21'),
(18, 21, 947, 23.90, '1', '', '', '', NULL, '2018-05-23'),
(19, 22, 947, 10.50, '1', '', '', '', NULL, '2018-05-23'),
(20, 20, 947, 15.90, '1', '', '', '', NULL, '2018-05-23'),
(21, 13, 947, 49.90, '1', '', '', '', NULL, '2018-05-23'),
(22, 23, 948, 14.90, '1', '', '', '', NULL, '2018-05-24'),
(23, 24, 961, 14.90, '1', NULL, NULL, NULL, NULL, '2018-05-27'),
(24, 12, 961, 5.90, '4', NULL, NULL, NULL, NULL, '2018-05-27'),
(32, 28, 967, 8.50, '2', NULL, NULL, NULL, NULL, '2018-05-28'),
(33, 29, 972, 12.90, '1', NULL, NULL, NULL, '1', '2018-05-29'),
(34, 30, 973, 6.50, '2', NULL, NULL, NULL, NULL, '2018-05-29'),
(35, 31, 976, 10.00, '1', NULL, NULL, NULL, NULL, '2018-05-30'),
(36, 32, 976, 10.00, '1', NULL, NULL, NULL, NULL, '2018-05-30');
As mentioned in my comment to your request: You forgot the ON clause that links the products_prices table to the other two.
MariaDB nastily converts your inner join into a cross join instead of raising an error as it should. What this gives you is: select all prices for product 30 combined with all places multiplied with the number of products therein, instead of just combined with the product's place.
By the way: I'd put table products first in the FROM clause, because this is the base (you want product 30). Then join the product's prices and the product's place.
There is no reason to group your data, as you only want to list the prices. You are not aggregating anything. So you get:
SELECT
pl.id AS place_id,
pl.data_name AS place_name,
pp.data_price AS product_price,
pp.date_updated AS price_updated
FROM products AS pr
JOIN products_prices AS pp ON pp.id_product = pr.id
JOIN places pl ON pl.id = pr.id_place
WHERE pr.id = 30
ORDER BY pp.data_price DESC, pp.date_updated DESC;
Try this:
SELECT PL.id AS place_id,
PL.data_name AS place_name,
PP.data_price AS product_price,
PP.date_updated AS price_updated
FROM products_prices PP
JOIN products PR
ON PR.id = PP.id_product
JOIN places PL
ON PL.id = PR.id_place
WHERE PR.id = '30'
Trying to create a query to select all jobs that are unpaid and who the customer is for that job.
So the is required to first work out a calculation of what they owe (by a sum of s_partorders qty x price found in s_parts) and then minus what they have paid from s_payments.
This query joins it all together but I don't know how to group it by jobNumber because there can be multiple payments and multiple part orders.
SELECT a.jobNumber, a.customerID, a.quoteStatus, a.costDelivery, a.costCallout, a.costLabour, b.customerID, b.firstName, b.lastName, c.paymentID, c.jobNumber, c.amount, d.orderID, d.jobNumber, d.partID, d.quantity, e.partID, e.sellPrice
FROM s_jobcards a
INNER JOIN s_customers b ON a.customerID = b.customerID
INNER JOIN s_payments c ON a.jobNumber = c.jobNumber
INNER JOIN s_partOrders d ON a.jobNumber = d.jobNumber
INNER JOIN s_parts e ON d.partID = e.partID
WHERE a.quoteStatus = 0
Sorry it's quite messy and incomplete...
Included table structure and some test data.
CREATE TABLE IF NOT EXISTS `s_customers` (
`customerID` int(20) NOT NULL AUTO_INCREMENT,
`firstName` text NOT NULL,
`lastName` text NOT NULL,
`address` text NOT NULL,
`suburb` text NOT NULL,
`state` text NOT NULL,
`postcode` text NOT NULL,
`phone` text NOT NULL,
`altPhone` text NOT NULL,
`email` text NOT NULL,
`notes` text NOT NULL,
`postAddress` text NOT NULL,
`serviceDueDate` date NOT NULL,
PRIMARY KEY (`customerID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
INSERT INTO `s_customers` (`customerID`, `firstName`, `lastName`, `address`, `suburb`, `state`, `postcode`, `phone`, `altPhone`, `email`, `notes`, `postAddress`, `serviceDueDate`) VALUES
(1, 'David', 'Davinci', '654 Fake Road', 'Canning Vale', 'WA', '6164', '9546446', '45645646', 'dave#website.com', 'This guy is a butt', 'Cockburn Central', '2014-12-24'),
(2, 'Timmy', 'Trumpet', '69 something Street', 'Cockburn Central', 'WA', '6164', '9456456', '92344643', 'timmy#trumpet.com', 'Timmah?', '45 Timmy Street', '0000-00-00'),
(3, 'Jerry', 'Tester', '', '', '', '', '', '', '', '', '', '0000-00-00');
CREATE TABLE IF NOT EXISTS `s_jobcards` (
`jobNumber` int(6) NOT NULL AUTO_INCREMENT,
`dateReceived` date NOT NULL,
`workRequired` text NOT NULL,
`workCompleted` text NOT NULL,
`dateCompleted` date NOT NULL,
`customerID` int(5) NOT NULL,
`serviceTime` int(5) NOT NULL,
`serviceTech` int(1) NOT NULL,
`workOutstanding` text NOT NULL,
`quoteStatus` tinyint(1) NOT NULL DEFAULT '1',
`costDelivery` double NOT NULL,
`costCallout` double NOT NULL,
`costLabour` double NOT NULL,
PRIMARY KEY (`jobNumber`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;
INSERT INTO `s_jobcards` (`jobNumber`, `dateReceived`, `workRequired`, `workCompleted`, `dateCompleted`, `customerID`, `serviceTime`, `serviceTech`, `workOutstanding`, `quoteStatus`, `costDelivery`, `costCallout`, `costLabour`) VALUES
(1, '2013-11-18', 'Create new service software. Yeah! 4534', 'Not a whole lot yet.?', '0000-00-00', 1, 5, 2, 'Complete this software?', 0, 50, 90, 90),
(2, '2013-11-18', 'work required', 'work done!', '0000-00-00', 1, 1, 3, 'work outstanding', 0, 0, 0, 0),
(3, '2014-12-01', 'Work harder.23432432 gdf', 'Go go!', '2014-12-01', 2, 1, 3, '', 1, 0, 0, 0),
(4, '0000-00-00', 'Whack some moles.', '', '0000-00-00', 3, 0, 1, '', 1, 0, 0, 0),
(5, '0000-00-00', '', '', '0000-00-00', 1, 0, 0, '', 1, 0, 0, 0);
CREATE TABLE IF NOT EXISTS `s_partOrders` (
`orderID` int(11) NOT NULL AUTO_INCREMENT,
`jobNumber` int(11) NOT NULL,
`partID` int(11) NOT NULL,
`quantity` int(11) NOT NULL,
PRIMARY KEY (`orderID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
INSERT INTO `s_partOrders` (`orderID`, `jobNumber`, `partID`, `quantity`) VALUES
(2, 0, 1, 5),
(3, 1, 1, 2),
(4, 1, 1, 6);
CREATE TABLE IF NOT EXISTS `s_parts` (
`partID` int(10) NOT NULL AUTO_INCREMENT,
`partNumber` varchar(50) NOT NULL,
`partDescription` text NOT NULL,
`modelID` int(5) NOT NULL,
`buyPrice` double NOT NULL,
`sellPrice` double NOT NULL,
`notes` text NOT NULL,
PRIMARY KEY (`partID`),
UNIQUE KEY `partNumber` (`partNumber`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
INSERT INTO `s_parts` (`partID`, `partNumber`, `partDescription`, `modelID`, `buyPrice`, `sellPrice`, `notes`) VALUES
(1, '3453453453', 'Test Part', 1, 10.02, 30.5, 'This is a test part.');
CREATE TABLE IF NOT EXISTS `s_payments` (
`paymentID` int(11) NOT NULL AUTO_INCREMENT,
`amount` double NOT NULL,
`type` text NOT NULL,
`jobNumber` int(11) NOT NULL,
`paymentDate` date NOT NULL,
PRIMARY KEY (`paymentID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
INSERT INTO `s_payments` (`paymentID`, `amount`, `type`, `jobNumber`, `paymentDate`) VALUES
(2, 200, 'Visa', 1, '2014-12-05'),
(3, 20, 'Visa', 1, '2014-12-05');
Use outer joins where there might be no matching records, and aggregating data to jobnumber before joining will assist in ensuring the numbers are accurate:
select
j.jobNumber, j.customerID, j.quoteStatus, j.costDelivery, j.costCallout, j.costLabour
, c.customerID, c.firstName, c.lastName
, p.parts_sellprice
, sum(jp.amount) as paid
from s_jobcards as j
inner join s_customers as c on j.customerID = c.customerID
left outer join s_payments as jp on j.jobNumber = jp.jobNumber
left outer join (
select
d.jobNumber, sum(d.quantity * e.sellPrice) parts_sellprice
from s_partOrders d
left outer join s_parts e ON d.partID = e.partID
group by
d.jobNumber
) as p on j.jobNumber = p.jobNumber
group by
j.jobNumber, j.customerID, j.quoteStatus, j.costDelivery, j.costCallout, j.costLabour
, c.customerID, c.firstName, c.lastName
;
nb: I have assumed the sell price is multiplied by quantity
see this sqlfiddle demo: http://sqlfiddle.com/#!2/96f4c/1
select
j.jobNumber, j.customerID, j.quoteStatus, j.costDelivery, j.costCallout, j.costLabour
, c.customerID, c.firstName, c.lastName
, p.parts_sellprice
, sum(jp.amount) as paid
, (j.costDelivery + j.costCallout + j.costLabour + p.parts_sellprice) as Total_Cost
, (j.costDelivery + j.costCallout + j.costLabour + p.parts_sellprice) - sum(jp.amount) as Amount_Outstanding
from s_jobcards as j
inner join s_customers as c on j.customerID = c.customerID
left outer join s_payments as jp on j.jobNumber = jp.jobNumber
left outer join (
select
d.jobNumber, sum(d.quantity * e.sellPrice) parts_sellprice
from s_partOrders d
left outer join s_parts e ON d.partID = e.partID
group by
d.jobNumber
) as p on j.jobNumber = p.jobNumber
group by
j.jobNumber, j.customerID, j.quoteStatus, j.costDelivery, j.costCallout, j.costLabour
, c.customerID, c.firstName, c.lastName
;
i have a reporting query which have 2 long sub-query
SELECT r1.code_centre, r1.libelle_centre, r1.id_equipe, r1.equipe, r1.id_file_attente,
r1.libelle_file_attente,r1.id_date, r1.tranche, r1.id_granularite_de_periode,r1.granularite,
r1.ContactsTraites, r1.ContactsenParcage, r1.ContactsenComm, r1.DureeTraitementContacts,
r1.DureeComm, r1.DureeParcage, r2.AgentsConnectes, r2.DureeConnexion, r2.DureeTraitementAgents,
r2.DureePostTraitement
FROM
( SELECT cc.id_centre_contact, cc.code_centre, cc.libelle_centre, a.id_equipe, a.equipe,
a.id_file_attente, f.libelle_file_attente, a.id_date, g.tranche, g.id_granularite_de_periode,
g.granularite, sum(Nb_Contacts_Traites) as ContactsTraites,
sum(Nb_Contacts_en_Parcage) as ContactsenParcage,
sum(Nb_Contacts_en_Communication) as ContactsenComm,
sum(Duree_Traitement/1000) as DureeTraitementContacts,
sum(Duree_Communication / 1000 + Duree_Conference / 1000 + Duree_Com_Interagent / 1000) as DureeComm,
sum(Duree_Parcage/1000) as DureeParcage
FROM agr_synthese_activite_media_fa_agent a, centre_contact cc,
direction_contact dc, granularite_de_periode g, media m, file_attente f
WHERE m.id_media = a.id_media
AND cc.id_centre_contact = a.id_centre_contact
AND a.id_direction_contact = dc.id_direction_contact
AND dc.direction_contact ='INCOMING'
AND a.id_file_attente = f.id_file_attente
AND m.media = 'PHONE'
AND ( ( g.valeur_min = date_format(a.id_date,'%d/%m') and g.granularite = 'Jour')
or ( g.granularite = 'Heure' and a.id_th_heure = g.id_granularite_de_periode) )
GROUP by cc.id_centre_contact, a.id_equipe, a.id_file_attente, a.id_date, g.tranche,
g.id_granularite_de_periode) r1,
(
(SELECT cc.id_centre_contact,cc.code_centre, cc.libelle_centre, a.id_equipe, a.equipe,
a.id_date, g.tranche, g.id_granularite_de_periode,g.granularite,
count(distinct a.id_agent) as AgentsConnectes,
sum(Duree_Connexion / 1000) as DureeConnexion,
sum(Duree_en_Traitement / 1000) as DureeTraitementAgents,
sum(Duree_en_PostTraitement / 1000) as DureePostTraitement
FROM activite_agent a, centre_contact cc, granularite_de_periode g
WHERE ( g.valeur_min = date_format(a.id_date,'%d/%m') and g.granularite = 'Jour')
AND cc.id_centre_contact = a.id_centre_contact
GROUP BY cc.id_centre_contact, a.id_equipe, a.id_date, g.tranche, g.id_granularite_de_periode )
UNION
(SELECT cc.id_centre_contact,cc.code_centre, cc.libelle_centre, a.id_equipe, a.equipe,
a.id_date, g.tranche, g.id_granularite_de_periode,g.granularite,
count(distinct a.id_agent) as AgentsConnectes,
sum(Duree_Connexion / 1000) as DureeConnexion,
sum(Duree_en_Traitement / 1000) as DureeTraitementAgents,
sum(Duree_en_PostTraitement / 1000) as DureePostTraitement
FROM activite_agent a, centre_contact cc, granularite_de_periode g
WHERE ( g.granularite = 'Heure'
AND a.id_th_heure = g.id_granularite_de_periode)
AND cc.id_centre_contact = a.id_centre_contact
GROUP BY cc.id_centre_contact,a.id_equipe, a.id_date, g.tranche, g.id_granularite_de_periode)
) r2
WHERE r1.id_centre_contact = r2.id_centre_contact
AND r1.id_equipe = r2.id_equipe AND r1.id_date = r2.id_date
AND r1.tranche = r2.tranche AND r1.id_granularite_de_periode = r2.id_granularite_de_periode
GROUP BY r1.id_centre_contact , r1.id_equipe, r1.id_file_attente,
r1.id_date, r1.tranche, r1.id_granularite_de_periode
ORDER BY r1.code_centre, r1.libelle_centre, r1.equipe,
r1.libelle_file_attente, r1.id_date, r1.id_granularite_de_periode,r1.tranche
the EXPLAIN shows
| id | select_type | table | type| possible_keys | key | key_len | ref| rows | Extra |
'1', 'PRIMARY', '<derived3>', 'ALL', NULL, NULL, NULL, NULL, '2520', 'Using temporary; Using filesort'
'1', 'PRIMARY', '<derived2>', 'ALL', NULL, NULL, NULL, NULL, '4378', 'Using where; Using join buffer'
'3', 'DERIVED', 'a', 'ALL', 'fk_Activite_Agent_centre_contact', NULL, NULL, NULL, '83433', 'Using temporary; Using filesort'
'3', 'DERIVED', 'g', 'ref', 'Index_granularite,Index_Valeur_min', 'Index_Valeur_min', '23', 'func', '1', 'Using where'
'3', 'DERIVED', 'cc', 'ALL', 'PRIMARY', NULL, NULL, NULL, '6', 'Using where; Using join buffer'
'4', 'UNION', 'g', 'ref', 'PRIMARY,Index_granularite', 'Index_granularite', '23', '', '24', 'Using where; Using temporary; Using filesort'
'4', 'UNION', 'a', 'ref', 'fk_Activite_Agent_centre_contact,fk_activite_agent_TH_heure', 'fk_activite_agent_TH_heure', '5', 'reporting_acd.g.Id_Granularite_de_periode', '2979', 'Using where'
'4', 'UNION', 'cc', 'ALL', 'PRIMARY', NULL, NULL, NULL, '6', 'Using where; Using join buffer'
NULL, 'UNION RESULT', '<union3,4>', 'ALL', NULL, NULL, NULL, NULL, NULL, ''
'2', 'DERIVED', 'g', 'range', 'PRIMARY,Index_granularite,Index_Valeur_min', 'Index_granularite', '23', NULL, '389', 'Using where; Using temporary; Using filesort'
'2', 'DERIVED', 'a', 'ALL', 'fk_agr_synthese_activite_media_fa_agent_centre_contact,fk_agr_synthese_activite_media_fa_agent_direction_contact,fk_agr_synthese_activite_media_fa_agent_file_attente,fk_agr_synthese_activite_media_fa_agent_media,fk_agr_synthese_activite_media_fa_agent_th_heure', NULL, NULL, NULL, '20903', 'Using where; Using join buffer'
'2', 'DERIVED', 'cc', 'eq_ref', 'PRIMARY', 'PRIMARY', '4', 'reporting_acd.a.Id_Centre_Contact', '1', ''
'2', 'DERIVED', 'f', 'eq_ref', 'PRIMARY', 'PRIMARY', '4', 'reporting_acd.a.Id_File_Attente', '1', ''
'2', 'DERIVED', 'dc', 'eq_ref', 'PRIMARY', 'PRIMARY', '4', 'reporting_acd.a.Id_Direction_Contact', '1', 'Using where'
'2', 'DERIVED', 'm', 'eq_ref', 'PRIMARY', 'PRIMARY', '4', 'reporting_acd.a.Id_Media', '1', 'Using where'
don't know it very clear, but i think is the problem of seems it take full scaning
than i change all the sub-query to views(create view as select sub-query), and the result is the same
thanks for any advice
Subquery and view will most of the time give you same result speed-wise.
If your subquery is not variabe, consider creating table that has same structure as your view, and occasionally do:
truncate table my_table;
insert into my_table select * from my_view;
...to cache your subquery data. If properly indexed, it will marginalize time lost on storing results of subquery in table, if data is not that frequently changed, or at least if you don't need up-to-date information on second-to-second basis.
Here is the query that I am working on:
SELECT `unitid`, `name` FROM apartmentunits
WHERE aptid = (
SELECT `aptid` FROM rentconditionsmap WHERE rentcondid = 1 AND condnum = 1
)
What I am having trouble figuring out is how to write this to add more rentcondition limiters to filter this list down more.
SELECT `aptid` FROM rentconditionsmap WHERE rentcondid = 1 AND condnum = 1
Data:
CREATE TABLE IF NOT EXISTS `rentconditionsmap` (
`rcid` bigint(10) unsigned NOT NULL AUTO_INCREMENT,
`rentcondid` int(3) unsigned NOT NULL,
`condnum` tinyint(3) unsigned NOT NULL,
`aptid` bigint(10) unsigned DEFAULT NULL,
PRIMARY KEY (`rcid`), KEY `aptid` (`aptid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=18 ;
INSERT INTO `rentconditionsmap`
(`rcid`, `rentcondid`, `condnum`, `aptid`)
VALUES
(1, 1, 1, 1),
(2, 2, 1, 1),
(3, 3, 0, 1),
(4, 4, 1, 1),
(5, 8, 0, 1);
CREATE TABLE IF NOT EXISTS `apartmentunits` (
`unitid` bigint(10) NOT NULL AUTO_INCREMENT,
`aptid` bigint(10) NOT NULL,
`name` varchar(6) NOT NULL,
`verified` tinyint(1) NOT NULL DEFAULT '0',
`rentcost` int(4) unsigned DEFAULT NULL,
`forrent` tinyint(1) NOT NULL DEFAULT '0',
`unittypekey` varchar(2) DEFAULT NULL,
`sqft` smallint(6) DEFAULT NULL,
PRIMARY KEY (`unitid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=121 ;
INSERT INTO `apartmentunits`
(`unitid`, `aptid`, `name`, `verified`, `rentcost`, `forrent`, `unittypekey`, `sqft`)
VALUES
(1, 1, '3', 1, 540, 0, '2B', NULL),
(2, 1, '5', 1, NULL, 0, '2B', NULL),
(3, 1, '7', 1, NULL, 0, '2B', NULL),
(53, 1, '1', 1, NULL, 0, '2B', NULL),
(54, 1, '2', 1, NULL, 0, '2B', NULL),
(55, 1, '4', 1, 570, 0, '2B', NULL),
(56, 1, '6', 1, NULL, 0, '2B', NULL),
(57, 1, '8', 1, NULL, 0, '2B', NULL),
(58, 1, '9', 1, NULL, 0, '2B', NULL),
(59, 1, '10', 1, NULL, 0, '2B', NULL),
(60, 1, '11', 1, NULL, 0, '2B', NULL);
As Eric J said as a comment:
Try changing = to IN
SELECT `unitid`, `name` FROM apartmentunits
WHERE `aptid` IN (
SELECT `aptid` FROM rentconditionsmap WHERE rentcondid = 1 AND condnum = 1
)
why not:
SELECT unitid, name
FROM apartmentunits a
INNER JOIN rentconditionsmap r on a.aptid = r.aptid
WHERE (rentcondid = 1 and condnum = 1) OR (rentcondid = 2 and condnum = 2)
Using ANSI-92 join syntax:
SELECT au.unitid,
au.name
FROM APARTMENTUNITS au
JOIN RENTCONDITIONSMAP rcm ON rcm.aptid = au.aptid
AND rcm.rentcondid = 1
AND rcm.condnum = 1
Use a JOIN (below is TSQL sintax for a join, or you can use the explicit INNER JOIN).
SELECT apartmentunits.unitid, apartmentunits.name
FROM apartmentunits, rentconditionsmap
WHERE apartmentunits.aptid = rentconditionsmap.aptid
AND rentconditionsmap.rentcondid = 1
AND rentconditionsmap.condnum = 1
-- AND whatever else...