Bug in MySQL query due to comparisons during joins - mysql

MySQL Server version: 5.5.41-0+wheezy1 - (Debian)
I've got a MySQL issue that is almost a year old. Have tried a few freelancers and while we got close, it was never totally solved.
I need to find the most recent outbound shipment for every product we have. And in the same row of results, the specific lot (including lot number and expiration date) of the product that was involved in that inventory adjustment.
The most recent version of this query is almost working but it has one fatal flaw (at least one). If the product only ever had one outbound shipment, it won't show up in the results. I'm assuming that is because on line 30 where a comparison is done, which looks like this
AND liai0.LocationInventoryAdjustmentItemID > liai.LocationInventoryAdjustmentItemID
I'm assuming it is because the one and only adjustment for a product couldn't be greater than itself, it fails to be considered by the where clause. I've tested this by adding a second, fake outbound shipment, for a missing product. The query then returns the missing product.
That isn't the only line with a comparison like that. Perhaps the same problem could happen if there was only ever one location for a given product (line 23) and perhaps if there was only ever one lot for a product (line 16).
Here is the latest version of the query:
SELECT
p.`ProductID`,
p.`ProductName`,
lot.`ProductLotID`,
lot.`ExpirationDate`,
lot.`LotNumber`,
lia.`LocationInventoryAdjustmentID`,
lia.`Created`,
liai.`count`
FROM products AS p
INNER JOIN product_lots AS lot ON lot.ProductID = p.ProductID
AND NOT EXISTS (
SELECT 1
FROM product_lots AS lot0
WHERE lot0.ProductID = lot.ProductID
AND lot0.ProductLotID > lot.ProductLotID
)
INNER JOIN product_locations AS pl ON pl.ProductLotID = lot.ProductLotID
AND NOT EXISTS (
SELECT 1
FROM product_locations AS pl0
WHERE pl0.ProductLotID = pl.ProductLotID
AND pl0.ProductLocationID > pl.ProductLocationID
)
INNER JOIN location_inventory_adjustment_items AS liai ON liai.ProductLocationID = pl.ProductLocationID
AND NOT EXISTS (
SELECT 1
FROM location_inventory_adjustment_items AS liai0
WHERE liai0.ProductLocationID = liai.ProductLocationID
AND liai0.LocationInventoryAdjustmentItemID > liai.LocationInventoryAdjustmentItemID
)
INNER JOIN location_inventory_adjustments AS lia ON lia.LocationInventoryAdjustmentID = liai.LocationInventoryAdjustmentID
INNER JOIN location_inventory_adjustment_reasons AS liar ON liar.ReasonID = lia.ReasonID
WHERE liar.`Name` LIKE '%Out-Bound%'
ORDER BY p.ProductID ASC, liai.LocationInventoryAdjustmentID
And now the tables
Table products
ProductID ProductName
1 Banana
2 Apple
3 Orange
4 Shirt
Table product_lots
ProductLotID ProductID ExpirationDate LotNumber
20 1 2022-01-01 Chikita22
21 3 2023-12-01 Florida-9
22 4 NULL HANES-001
23 1 2024-01-01 Chikita24
Table product_locations
ProductLocationID ProductLotID LocationCode LocationType
30 20 A-01-01-01 1
31 21 A-02-01-01 1
32 22 12-03-01-01 2
33 23 A-01-01-01 1
Table location_inventory_adjustment_items
LocationInventoryAdjustmentItemID LocationInventoryAdjustmentID ProductLocationID Count
40 50 30 100
41 51 31 200
42 52 32 300
43 53 33 150
Table location_inventory_adjustments
LocationInventoryAdjustmentID LocationTypeID ReasonID Created
50 1 4 2020-01-01
51 1 4 2020-05-01
52 2 4 2020-06-01
53 1 4 2020-07-07
Table location_inventory_adjustment_reasons
ReasonID Name Description
1 Discarded Product Trash
2 In-Bound Shipment Delivery
3 Out-Bound Shipment Product was shipped out
4 Out-Bound Shipment - FBA US Product was shipped out to an Amazon fulfillment center in the US
5 Out-Bound Shipment - FBA UK Product was shipped out to an Amazon fulfillment center in the UK
Now that the table structure is added, only the product Banana would be returned by the query since it is the only product to be involved in more than one inventory adjustment (more than one outbound shipment).
What can I do to fix this bug (in my query, obviously not a bug in MySQL)

Ican't really explain it it must be one or other restricted wording.
But try, at least mysql 8 workbench doesn't mind
CREATE TABLE products
(`ProductID` int, `ProductName` varchar(6))
;
INSERT INTO products
(`ProductID`, `ProductName`)
VALUES
(1, 'Banana'),
(2, 'Apple'),
(3, 'Orange'),
(4, 'Shirt')
;
✓
✓
CREATE TABLE product_lots
(`ProductLotID` int, `ProductID` int, `ExpirationDate` varchar(10), `LotNumber` varchar(9))
;
INSERT INTO product_lots
(`ProductLotID`, `ProductID`, `ExpirationDate`, `LotNumber`)
VALUES
(20, 1, '2022-01-01', 'Chikita22'),
(21, 3, '2023-12-01', 'Florida-9'),
(22, 4, NULL, 'HANES-001'),
(23, 1, '2024-01-01', 'Chikita24')
;
✓
✓
CREATE TABLE product_locations
(`ProductLocationID` int, `ProductLotID` int, `LocationCode` varchar(11), `LocationType` int)
;
INSERT INTO product_locations
(`ProductLocationID`, `ProductLotID`, `LocationCode`, `LocationType`)
VALUES
(30, 20, 'A-01-01-01', 1),
(31, 21, 'A-02-01-01', 1),
(32, 22, '12-03-01-01', 2),
(33, 23, 'A-01-01-01', 1)
;
✓
✓
CREATE TABLE location_inventory_adjustment_items
(`LocationInventoryAdjustmentItemID` int, `LocationInventoryAdjustmentID` int, `ProductLocationID` int, `Count` int)
;
INSERT INTO location_inventory_adjustment_items
(`LocationInventoryAdjustmentItemID`, `LocationInventoryAdjustmentID`, `ProductLocationID`, `Count`)
VALUES
(40, 50, 30, 100),
(41, 51, 31, 200),
(42, 52, 32, 300),
(43, 53, 33, 150)
;
✓
✓
CREATE TABLE location_inventory_adjustments
(`LocationInventoryAdjustmentID` int, `LocationTypeID` int, `ReasonID` int, `Created` date)
;
INSERT INTO location_inventory_adjustments
(`LocationInventoryAdjustmentID`, `LocationTypeID`, `ReasonID`, `Created`)
VALUES
(50, 1, 4, '2020-01-01'),
(51, 1, 4, '2020-05-01'),
(52, 2, 4, '2020-06-01'),
(53, 1, 4, '2020-07-07')
;
✓
✓
CREATE TABLE location_inventory_adjustment_reasons
(`ReasonID` int, `Name` varchar(27), `Description` varchar(65))
;
INSERT INTO location_inventory_adjustment_reasons
(`ReasonID`, `Name`, `Description`)
VALUES
(1, 'Discarded Product', 'Trash'),
(2, 'In-Bound Shipment', 'Delivery'),
(3, 'Out-Bound Shipment', 'Product was shipped out'),
(4, 'Out-Bound Shipment - FBA US', 'Product was shipped out to an Amazon fulfillment center in the US'),
(5, 'Out-Bound Shipment - FBA UK', 'Product was shipped out to an Amazon fulfillment center in the U')
;
✓
✓
SELECT
p.`ProductID`,
p.`ProductName`,
lot.`ProductLotID`,
lot.`ExpirationDate`,
lot.`LotNumber`,
lia.`LocationInventoryAdjustmentID`,
lia.`Created`,
liai.`count`
FROM products AS p
INNER JOIN product_lots AS lot ON lot.ProductID = p.ProductID
AND NOT EXISTS (
SELECT 1
FROM product_lots AS lot0
WHERE lot0.ProductID = lot.ProductID
AND lot0.ProductLotID > lot.ProductLotID
)
INNER JOIN product_locations AS pl ON pl.ProductLotID = lot.ProductLotID
AND NOT EXISTS (
SELECT 1
FROM product_locations AS pl0
WHERE pl0.`ProductLotID` = pl.`ProductLotID`
AND pl0.ProductLocationID > pl.ProductLocationID
)
INNER JOIN location_inventory_adjustment_items AS liai ON liai.ProductLocationID = pl.ProductLocationID
AND NOT EXISTS (
SELECT 1
FROM location_inventory_adjustment_items AS liai0
WHERE liai0.ProductLocationID = liai.ProductLocationID
AND liai0.`LocationInventoryAdjustmentItemID` > liai.`LocationInventoryAdjustmentItemID`
)
INNER JOIN location_inventory_adjustments AS lia ON lia.LocationInventoryAdjustmentID = liai.LocationInventoryAdjustmentID
INNER JOIN location_inventory_adjustment_reasons AS liar ON liar.ReasonID = lia.ReasonID
WHERE liar.`Name` LIKE '%Out-Bound%'
ORDER BY p.ProductID ASC, liai.LocationInventoryAdjustmentID
ProductID | ProductName | ProductLotID | ExpirationDate | LotNumber | LocationInventoryAdjustmentID | Created | count
--------: | :---------- | -----------: | :------------- | :-------- | ----------------------------: | :--------- | ----:
1 | Banana | 23 | 2024-01-01 | Chikita24 | 53 | 2020-07-07 | 150
3 | Orange | 21 | 2023-12-01 | Florida-9 | 51 | 2020-05-01 | 200
4 | Shirt | 22 | null | HANES-001 | 52 | 2020-06-01 | 300
db<>fiddle here

Related

MySQL Update a table by min of another table

I would like to update Table Lease from Table History
CREATE TABLE Lease
(`LeaseID` int, `Name` varchar(3), `Users` varchar(15), `WhoSignID` int, `NoteDate` date)
;
INSERT INTO Lease
(`LeaseID`, `Name`, `Users`, `WhoSignID`, `NoteDate`)
VALUES
(1, 'AAA', '1000,1001', NULL, NULL),
(2, 'BBB', '1002', NULL, NULL),
(3, 'CCC', '1003,1004', NULL, NULL),
(4, 'DDD', '1005,1006, 1007', NULL, NULL)
;
CREATE TABLE History
(`HistoryID` int, `LeaseID` int, `User` int, `SignDate` date)
;
INSERT INTO History
(`HistoryID`, `LeaseID`, `User`, `SignDate`)
VALUES
(1, 1, 1000, '2020-01-05'),
(2, 1, 1001, '2020-01-04'),
(3, 1, 1001, '2020-01-02'),
(4, 1, 1000, '2020-01-03'),
(6, 2, 1002, '2020-05-01'),
(7, 2, 1002, '2020-05-03')
;
I looking of a Mysql Update to update Table Lease :
NoteDate and WhoSignID based on SignDate and User
where Minimum of SignDate of User
Table Lease After Update
LeaseID | Name | Users | WhoSignID | NoteDate
1 | AAA | 1000,1001 | 1001 | 2020-01-02
2 | BBB | 1002 | 1002 | 2020-05-01
...
I appreciate any assist
Your Lease table has a serious design problem, because it is storing users as a CSV list. Instead, you should have each user value on a separate record. That being said, it appears that the CSV user list is immaterial to your current problem, which only required finding the earliest date for each lease. If so, then a simple update join should suffice:
UPDATE Lease l
INNER JOIN
(
SELECT h1.LeaseID, h1.User, h2.MinSignDate
FROM History h1
INNER JOIN
(
SELECT LeaseID, MIN(SignDate) AS MinSignDate
FROM History
GROUP BY LeaseID
) h2
ON h2.LeaseID = h1.LeaseID AND
h2.MinSignDate = h1.SignDate
) h
ON h.LeaseID = l.LeaseID
SET
WhoSignID = h.User,
NoteDate = h.MinSignDate;

Case, group by , join on multiple table

I have 3 tables transaction , store and date. A column in store table needs to be assigned values based on conditions and that new column needs to be used in group by.
ASK is to find ` total sales across different banners for a particular time period.
i am using following query..
"""select sum(net_spend) as sales , d.fis_week_id, st.banner
from ( select s*,
CASE WHEN st.format IN ('S','S MINI','S HYPER') THEN 'S'
WHEN st.format = 'CHECKERS' THEN 'CHECKERS'
ELSE st.format END AS banner
from store_dim s) st
from transaction_item_fct tr
inner join date_dim d on d.date_id = tr.date_id
inner join store_dim_c s on st.store_id = tr.store_id
where d.fis_week_id >=201809 and d.fis_week_id<=201813
and tr.store_id = st.store_id
group by st.banner, d.fis_week_id
"""
Where I am getting wrong?
Below is the fabricated tables' data
Transaction table-
store_id week_id net_spend
1 12 345
1 11 788
2 13 556
3 11 300
Store table
store_id format
1 S
2 S MINI
3 S Hyper
4 Checker
Date table
week_id fis_week_id
11 201712
12 201717
Result expected is
week_id banner spend
11 S 888
11 Hyper 666
It's not 100% clear from your question but I think this query will do what you want. You will need to change the WHERE condition on d.fis_week_id as appropriate for your needs, I have made it appropriate for the demo case I set up.
SELECT d.week_id, st.banner, SUM(t.net_spend) AS sales, d.fis_week_id
FROM date_dim d
LEFT JOIN transaction_item t ON t.week_id = d.week_id
JOIN (SELECT store_id,
CASE WHEN format IN ('S', 'S MINI', 'S Hyper') THEN 'S'
WHEN format = 'Checker' THEN 'Checker'
ELSE format
END AS banner
FROM store_dim s) st
ON st.store_id = t.store_id
WHERE d.fis_week_id BETWEEN 201712 AND 201720
GROUP BY d.week_id, st.banner
I've expanded your demo data out a bit and created a test case at SQLFiddle:
CREATE TABLE transaction_item
(`store_id` int, `week_id` int, `net_spend` int);
INSERT INTO transaction_item
(`store_id`, `week_id`, `net_spend`)
VALUES (1, 12, 345), (1, 11, 788), (2, 13, 556), (3, 11, 300),
(4, 11, 440), (4, 12, 123), (5, 11, 100), (6, 13, 444);
CREATE TABLE store_dim
(`store_id` int, `format` varchar(7));
INSERT INTO store_dim
(`store_id`, `format`)
VALUES (1, 'S'), (2, 'S MINI'), (3, 'S Hyper'), (4, 'Checker'), (5, 'Checker'), (6, 'Other');
CREATE TABLE date_dim
(`week_id` int, `fis_week_id` int);
INSERT INTO date_dim
(`week_id`, `fis_week_id`)
VALUES (11, 201712), (12, 201717), (13, 201720);
Output:
week_id banner sales fis_week_id
11 Checker 540 201712
11 S 1088 201712
12 Checker 123 201717
12 S 345 201717
13 Other 444 201720
13 S 556 201720

MySQL Fetch Result Using Multiple Joins in one query?

I have below tables
tbl_user
uid first_name last_name email_id
1 steve martin steve1#gmail.com
2 mark lee mark1#gmail.com
3 nelson wise nelson23#gmail.com
tbl_tier
tier_id tier_name points_required
1 Silver 100
2 Gold 200
3 Platinum 300
tbl_tier_earned
id tier_id uid
1 1 1
2 2 1
3 3 1
4 1 2
5 2 2
6 1 3
I need unique users with their current tiers like:
first_name last_name email_id current_tier
steve martin steve1#gmail.com Platinum
mark lee mark1#gmail.com Gold
I have tried below query but it gives me only 1 result:
SELECT u.first_name,u.last_name,u.email_id, t.tier_name
FROM tbl_tier_earned AS tte
INNER JOIN tbl_user AS u
ON u.uid = tte.uid
INNER JOIN tbl_tier AS t
ON tte.tier_id = t.tier_id
WHERE u.email_id!=""
ORDER BY t.points_required DESC LIMIT 0,1
How can I retrieve above data using mysql query?
It appears that the current tier is given by the max tier_id in the tbl_tier_earned table, for each user. One approach here would be to join the user table to a subquery on the tbl_tier_earned table which finds the max tier.
SELECT
u.first_name,
u.last_name,
u.email_id,
COALESCE(t2.tier_name, 'NA') AS current_tier
FROM tbl_user u
LEFT JOIN
(
SELECT uid, MAX(tier_id) AS max_tier_id
FROM tbl_tier_earned
GROUP BY uid
) t1
ON u.uid = t1.uid
LEFT JOIN tbl_tier t2
ON t1.max_tier_id = t2.tier_id;
SQL Fiddle
MySQL 5.6 Schema Setup:
CREATE TABLE tbl_user
(`uid` int, `first_name` varchar(6), `last_name` varchar(6), `email_id` varchar(18))
;
INSERT INTO tbl_user
(`uid`, `first_name`, `last_name`, `email_id`)
VALUES
(1, 'steve', 'martin', 'steve1#gmail.com'),
(2, 'mark', 'lee', 'mark1#gmail.com'),
(3, 'nelson', 'wise', 'nelson23#gmail.com')
;
CREATE TABLE tbl_tier
(`tier_id` int, `tier_name` varchar(8), `points_required` int)
;
INSERT INTO tbl_tier
(`tier_id`, `tier_name`, `points_required`)
VALUES
(1, 'Silver', 100),
(2, 'Gold', 200),
(3, 'Platinum', 300)
;
CREATE TABLE tbl_tier_earned
(`id` int, `tier_id` int, `uid` int)
;
INSERT INTO tbl_tier_earned
(`id`, `tier_id`, `uid`)
VALUES
(1, 1, 1),
(2, 2, 1),
(3, 3, 1),
(4, 1, 2),
(5, 2, 2),
(6, 1, 3)
;
Query 1:
SELECT c.first_name, c.last_name, c.email_id,
(SELECT tier_name from tbl_tier WHERE points_required = max(b.points_required)) as current_tier
FROM tbl_tier_earned a
INNER JOIN tbl_tier b ON a.tier_id = b.tier_id
INNER JOIN tbl_user c ON a.uid = c.uid
GROUP BY c.first_name, c.last_name, c.email_id
Results:
| first_name | last_name | email_id | current_tier |
|------------|-----------|--------------------|--------------|
| mark | lee | mark1#gmail.com | Gold |
| nelson | wise | nelson23#gmail.com | Silver |
| steve | martin | steve1#gmail.com | Platinum |

SELECT from multiple tables with cross-references and self-references [brain cracker]

Anyone up to an SQL challenge? Cause all my efforts so far are barely enough to simplify the problem and put it in a question...
Here it goes. In the example below we need to include:
All paid flights
Flights to a country (paid or not) if a person has made another flight to a paid city in that country
It's already tricky, but there is more to it.
If a person flies to a city with no entry fee, but it is located in a
country that DOES have a fee, that flight is still considered paid
and must be included as well.
EDIT: I've added flight 110, which should help reveal unnecessarily added free fligts.
Below is the result set that should come out of the SQL query:
+--------------------------------------------------------------+
| Desired result set |
+--------------------------------------------------------------+
| FlightNumber | ID | Name | LocationID | location.Name |
+--------------------------------------------------------------+
| 102 | 2 | Tom | 500 | NL - NoFee | -> because Tom has a paid flight to Amsterdam
| 103 | 2 | Tom | 501 | Amsterdam (NL) - Fee | -> because Amsterdam is a paid location
| 105 | 4 | Bob | 501 | Amsterdam (NL) - Fee | -> because Amsterdam is a paid location
| 107 | 6 | Bill | 503 | ITA - Fee | -> because ITA is a paid location
| 108 | 7 | Ryan | 503 | ITA - Fee | -> because ITA is a paid location
| 109 | 7 | Ryan | 505 | Venice (ITA) - NoFee | -> because Venice is located inside ITA
+--------------------------------------------------------------+
Does anyone know how get this sweet result set with SQL?
A good place to start:
SELECT flights.FlightNumber, people.ID, people.Name, flights.LocationID, locations.Name
FROM flights
INNER JOIN people ON (people.ID = flights.ID)
INNER JOIN locations ON (locations.LocationID = flights.LocationID)
CREATE/INSERT
CREATE TABLE `people` (
`ID` INT NOT NULL,
`Name` VARCHAR(45) NULL,
PRIMARY KEY (`ID`) );
CREATE TABLE `locations` (
`LocationID` INT NOT NULL,
`Name` VARCHAR(45) NULL,
`EntryFee` TINYINT(1) NULL,
`ParentLocationID` INT NULL,
PRIMARY KEY (`LocationID`) );
CREATE TABLE `flights` (
`FlightNumber` INT NOT NULL,
`ID` INT NULL,
`LocationID` INT NULL,
PRIMARY KEY (`FlightNumber`) ,
INDEX `fk_purchases_buyers_idx` (`LocationID` ASC) ,
INDEX `fk_flights_people1_idx` (`ID` ASC) ,
CONSTRAINT `fk_purchases_buyers`
FOREIGN KEY (`LocationID`)
REFERENCES `locations` (`LocationID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_flights_people1`
FOREIGN KEY (`ID`)
REFERENCES `people` (`ID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION);
INSERT INTO `people` (`ID`, `Name`) VALUES
(1, 'John'),
(2, 'Tom'),
(3, 'Kate'),
(4, 'Bob'),
(5, 'Mike'),
(6, 'Bill'),
(7, 'Ryan');
INSERT INTO `locations` (`LocationID`, `Name`, `EntryFee`, `ParentLocationID`) VALUES
(500, 'NL - NoFee', 0, NULL),
(501, 'Amsterdam (NL) - Fee', 1, 500),
(502, 'Rotterdam (NL) - NoFee', 0, 500),
(503, 'ITA - Fee', 1, NULL),
(504, 'Rome (ITA) - Fee', 1, 503),
(505, 'Venice (ITA) - NoFee', 0, 503);
INSERT INTO `flights` VALUES
(100, 1, 500),
(101, 1, 502),
(102, 2, 500),
(103, 2, 501),
(104, 3, 500),
(105, 4, 501),
(106, 5, 502),
(107, 6, 503),
(108, 7, 503),
(109, 7, 505),
(110, 6, 502);
Unimportant note: I know this example is not completely logical in a sense of storing countries and cities in the same table and having flight records to a country and to a city. But this is just an example. At least it's more readable than t1.col1-like stuff.
Following should work :
SELECT F.FlightNumber, P.ID, P.Name, F.LocationID, LOC.Name AS Loc_Name
FROM flights F
INNER JOIN people P ON P.ID = F.ID
INNER JOIN (SELECT L1.LocationID, L1.`Name`, L1.`ParentLocationID`
FROM locations L1
LEFT JOIN locations L2 ON L1.`ParentLocationID` = L2.LocationID
WHERE L1.`EntryFee` = 1 OR L2.`EntryFee` = 1) AS LOC ON LOC.LocationID = F.LocationID
UNION
SELECT F.FlightNumber, PAID_FL.ID, PAID_FL.Name, F.LocationID, PAID_FL.Loc_Name
FROM flights F
INNER JOIN (SELECT F.FlightNumber, P.ID, P.Name, LOC.Name AS Loc_Name,LOC.`ParentLocationID` AS LocationID
FROM flights F
INNER JOIN people P ON P.ID = F.ID
INNER JOIN (SELECT L1.LocationID, L1.`ParentLocationID`, L2.`Name`
FROM locations L1
LEFT JOIN locations L2 ON L1.`ParentLocationID` = L2.LocationID
WHERE L1.`EntryFee` = 1 OR L2.`EntryFee` = 1) AS LOC ON LOC.LocationID = F.LocationID) PAID_FL ON F.ID = PAID_FL.ID AND F.LocationID = PAID_FL.LocationID
I didn't do any testing, but I think this will work:
SELECT F.FlightNumber, P.ID, P.Name, L.LocationID, L.Name
FROM flights F
INNER JOIN people P ON P.ID = F.ID
INNER JOIN locations L ON L.LocationID = F.LocationID
WHERE P.ID IN (SELECT F.ID FROM flights F INNER JOIN locations L ON L.LocationID = F.LocationID WHERE L.EntryFee = 1)
See it at SQLFiddle.com.
SELECT x.*
, COALESCE(y.entryfee,x.entryfee,0) fee
FROM locations x
LEFT
JOIN locations y
ON y.parentlocationid = x.locationid;

Get rolled up sub total and total by joining multiple tables

Extending Rolling up addition using mysql
I can get rolling sum of rows https://stackoverflow.com/users/1529673/strawberry's answer for basic stuff so i tried to extend query by joining multiple tables but 1_keyworddefs.name='K2' is not affected. Getting same answer for 1_keyworddefs.name='K1' and K2.
Working query but directly by specifying 1_bugs.bug_id='2':
SELECT x.*, x.cf1 + x.cf2 sub_total, sum(y.cf1 + y.cf2) total FROM 1_bugs x INNER JOIN 1_bugs y ON y.bug_id <= x.bug_id INNER JOIN 1_keywords ON 1_keywords.bug_id = y.bug_id WHERE (x.bug_date BETWEEN '2016-07-19' AND '2016-07-22') AND (x.bug_id='2') AND (y.bug_status = 'VERIFIED' OR y.bug_status = 'CLOSED') AND (1_keywords.bug_id = x.bug_id) GROUP BY x.bug_id
Exact output (but i want to join table where 1_keywords.bug_id=1_bugs.bug_id matches instead of directly specifying 1_bugs.bug_id='2'):
bug_id bug_date cf1 cf2 bug_status sub_total total
2 2016-07-19 2 1 VERIFIED 3 3
Non-working query by joining tables (expecting answer like above):
SELECT x.*, x.cf1 + x.cf2 sub_total, sum(y.cf1 + y.cf2) total FROM 1_bugs x INNER JOIN 1_bugs y ON y.bug_id <= x.bug_id LEFT JOIN 1_keywords ON 1_keywords.bug_id = y.bug_id LEFT JOIN 1_keyworddefs ON 1_keyworddefs.id=1_keywords.keywordid AND 1_keyworddefs.name='K2' and 1_keywords.bug_id = y.bug_id WHERE (x.bug_date BETWEEN '2016-07-19' AND '2016-07-22') AND (y.bug_status = 'CLOSED' OR y.bug_status = 'VERIFIED') GROUP BY x.bug_id;
Expected:
bug_id bug_date cf1 cf2 bug_status sub_total total
2 2016-07-19 2 1 VERIFIED 3 3
Actual:
bug_id bug_date cf1 cf2 bug_status sub_total total
2 2016-07-19 2 1 VERIFIED 3 3
3 2016-07-22 2 2 CLOSED 4 7
** Here bug_id -> 3 row comes wrongly because 1_bugs.bug.id=1_keywords.bug_id doesn't match and there is no 1_keywords.bug_id='3' present in 1_keywords table.
DDLs:
-- 1_bugs table1 (master table) :
CREATE TABLE `1_bugs` (`bug_id` int(11) NOT NULL, `bug_date` date NOT NULL, `cf1` int(11) NOT NULL, `cf2` int(11) NOT NULL, `bug_status` varchar(200) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `1_bugs` (`bug_id`, `bug_date`, `cf1`, `cf2`, `bug_status`) VALUES (1, '2016-07-19', 3, 2, 'RESOLVED'), (2, '2016-07-19', 2, 1, VERIFIED'), (3, '2016-07-22', 2, 2, 'CLOSED');
-- 1_keywords table2 (having keyword ids):
CREATE TABLE `1_keywords` (`bug_id` int(11) NOT NULL, `keywordid` varchar(11) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `1_keywords` (`bug_id`, `keywordid`) VALUES (1, 'K1'), (2, 'K2');
-- 1_keyworddefs table3 (having keyword names according to keywordid):
CREATE TABLE `1_keyworddefs` (`id` int(11) NOT NULL, `name` varchar(200) NOT NULL, `description` varchar(200) NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `1_keyworddefs` (`id`, `name`, `description`) VALUES (1, 'K1', 'My K1 item'), (2, 'K2', 'My K2 item');
Can someone please point me what i'm doing wrong?
Obviously things where not clear... after long discussions turns out what you wanted was to extract from bugzilla database a list of bugs for specific keyword grouped by date and a sum of cf1 + cf2 and the same sum of only 'opened' and 'verified' bugs.
Here we go
SELECT
b.lastdiffed,
d.name,
d.description,
SUM(IF(b.bug_status IN('CLOSED', 'VERIFIED'), b.cf1 + b.cf2, 0)) AS sub_total,
SUM(b.cf1 + b.cf2) AS running
FROM
bugs AS b
JOIN keywords AS k
ON ( k.bug_id = b.bug_id )
JOIN keyworddefs AS d
ON ( d.id = k.keywordid )
WHERE
1
AND d.name = 'SONY'
GROUP BY (b.lastdiffed)
ORDER BY b.lastdiffed ASC
Giving this result
+------------+------+-------------+-----------+---------+
| lastdiffed | name | description | sub_total | running |
+------------+------+-------------+-----------+---------+
| 2016-05-20 | SONY | sony items | 7 | 7 |
| 2016-06-20 | SONY | sony items | 11 | 17 |
| 2016-06-27 | SONY | sony items | 5 | 5 |
| 2016-06-29 | SONY | sony items | 5 | 5 |
+------------+------+-------------+-----------+---------+
Hope this helps.