Do I need a CURSOR for this? - mysql

I am trying to step through a table and update an attribute based on the below query.
When I run the below, it set's all values to 52, so it is recognising the first case and applying to all values. If I remove the count from the select statements of the case I get an error saying it returns more than 1 row.
Each of the select statements are correct in returning the items that need to be updated when I run them individually. For instance, the select statement in the first case has 41 rows (products) that need updating to value '52', then another 14 rows for the second case, 35 for the next and 26 for the next.
I am going around in circles and I have absolutely no idea how to apply the value to the rows based on each of the select statements in the cases. I don't think a case statement is correct either now. Please help.
My thinking is along 'for each row in select statement update value = x where t1.taxonomy= 'pa_supplier and t1.product_id = table2.product_id where table2.sku = table4.VendorStockCode'. How to write this in mySQL though? Stumped...
UPDATE table1 t1
SET t1.term_id =
(
CASE
WHEN
(
SELECT COUNT(VendorStockCode) FROM table4 t4
JOIN table5 t5 WHERE t4.VendorStockCode= t5.Manufacture_Code AND EXISTS(SELECT sku FROM table2 WHERE table4.VendorStockCode = table2.sku) AND t4.StockAvailable > 0 AND t5.Stock_qty <= 0
) > 0
THEN '52'
WHEN
(
SELECT COUNT(VendorStockCode) FROM table4 t4
JOIN table5 t5 WHERE t4.VendorStockCode= t5.Manufacture_Code AND EXISTS(SELECT sku FROM table2 WHERE table4.VendorStockCode = table2.sku) AND t4.StockAvailable <= 0 AND t5.Stock_qty > 0
) > 0
THEN '51'
WHEN
(
SELECT COUNT(VendorStockCode) FROM table4 t4
JOIN table5 t5 WHERE t4.VendorStockCode= t5.Manufacture_Code AND EXISTS(SELECT sku FROM table2 WHERE table4.VendorStockCode = table2.sku) AND t4.StockAvailable > 0 AND t5.Stock_qty > 0 AND CAST(t4.DealerEx as decimal(10,2)) > cast(t5.ExTax as decimal(10,2))
) > 0
THEN '51'
WHEN
(
SELECT COUNT(VendorStockCode) FROM table4 t4
JOIN table5 t5 WHERE t4.VendorStockCode= t5.Manufacture_Code AND EXISTS(SELECT sku FROM table2 WHERE table4.VendorStockCode = table2.sku) AND t4.StockAvailable > 0 AND t5.Stock_qty > 0 AND CAST(t4.DealerEx as decimal(10,2)) <= cast(t5.ExTax as decimal(10,2))
) > 0
THEN '52'
ELSE t1.term_id
END
)
WHERE t1.taxonomy= 'pa_supplier';

Use a CTE
Try the query below it might need some syntax fixes:
WITH
trow AS (
Select * from table1 t1,
WHERE t1.taxonomy= 'pa_supplier')
UPDATE table1 t1
SET t1.term_id =
(
CASE
WHEN
(
SELECT COUNT(VendorStockCode) FROM table4 t4
JOIN table5 t5 WHERE t4.VendorStockCode= t5.Manufacture_Code AND EXISTS(SELECT sku FROM table2 WHERE table4.VendorStockCode = table2.sku) AND t4.StockAvailable > 0 AND t5.Stock_qty <= 0
) > 0
THEN '52'
WHEN
(
SELECT COUNT(VendorStockCode) FROM table4 t4
JOIN table5 t5 WHERE t4.VendorStockCode= t5.Manufacture_Code AND EXISTS(SELECT sku FROM table2 WHERE table4.VendorStockCode = table2.sku) AND t4.StockAvailable <= 0 AND t5.Stock_qty > 0
) > 0
THEN '51'
WHEN
(
SELECT COUNT(VendorStockCode) FROM table4 t4
JOIN table5 t5 WHERE t4.VendorStockCode= t5.Manufacture_Code AND EXISTS(SELECT sku FROM table2 WHERE table4.VendorStockCode = table2.sku) AND t4.StockAvailable > 0 AND t5.Stock_qty > 0 AND CAST(t4.DealerEx as decimal(10,2)) > cast(t5.ExTax as decimal(10,2))
) > 0
THEN '51'
WHEN
(
SELECT COUNT(VendorStockCode) FROM table4 t4
JOIN table5 t5 WHERE t4.VendorStockCode= t5.Manufacture_Code AND EXISTS(SELECT sku FROM table2 WHERE table4.VendorStockCode = table2.sku) AND t4.StockAvailable > 0 AND t5.Stock_qty > 0 AND CAST(t4.DealerEx as decimal(10,2)) <= cast(t5.ExTax as decimal(10,2))
) > 0
THEN '52'
ELSE t1.term_id
END
)
INNER JOIN table1 as t1
on trow.product_id=t1.product_id;

I finally got the below to work but takes a very long time to execute, but it is working.
UPDATE table1 t1
SET t1.term_id = 52 WHERE t1.taxonomy= 'pa_supplier' AND t1.product_id IN (
SELECT product_id FROM table2 t2
INNER JOIN table3 t3 ON t3.Manufacture_Code = t2.sku
INNER JOIN table4 t4 ON t4.VendorStockCode= t3.Manufacture_Code AND t4.StockAvailable > 0 AND t3.Stock_qty <= 0)
UPDATE table1 t1
SET t1.term_id = 51 WHERE t1.taxonomy= 'pa_supplier' AND t1.product_id IN (
SELECT product_id FROM table2 t2
INNER JOIN table3 t3 ON t3.Manufacture_Code = t2.sku
INNER JOIN table4 t4 ON t4.VendorStockCode= t3.Manufacture_Code AND t4.StockAvailable <= 0 AND t3.Stock_qty > 0)
UPDATE table1 t1
SET t1.term_id = 51 WHERE t1.taxonomy= 'pa_supplier' AND t1.product_id IN (
SELECT product_id FROM table2 t2
INNER JOIN table3 t3 ON t3.Manufacture_Code = t2.sku
INNER JOIN table4 t4 ON t4.VendorStockCode= t3.Manufacture_Code AND t4.StockAvailable > 0 AND t3.Stock_qty > 0 AND CAST(DealerEx as decimal(10,2)) > cast(ExTax as decimal(10,2)))
UPDATE table1 t1
SET t1.term_id = 52 WHERE t1.taxonomy= 'pa_supplier' AND t1.product_id IN (
SELECT product_id FROM table2 t2
INNER JOIN table3 t3 ON t3.Manufacture_Code = t2.sku
INNER JOIN table4 t4 ON t4.VendorStockCode= t3.Manufacture_Code AND t4.StockAvailable > 0 AND t3.Stock_qty > 0 AND CAST(DealerEx as decimal(10,2)) <= cast(ExTax as decimal(10,2)))

Related

postgres array_agg with distinct on json_build_object

select
t1.id,
array_agg(
json_build_object('id', t2.id, 'status', t2.status)
) as statuses
from table1 t1
inner join table2 t2 on t1.id=t2.user_id
inner join table3 t3 on t1.id=t3.user_id
group by t1.id
table1
id , user
1 , 'A'
2 , 'B'
table2
user_id , status
1 , 'P'
1 , 'AP'
table3
user_id , something
1 , 'A12'
1 , 'B1212'
the table3 also one-many relationship as a result the duplication of statuses coming in the array_agg,
i tried with array_agg(distinct json_build_object()) and array_agg(distinct on json_build_object()),
how can we prevent duplications in this case ??
Just filter out the relevant status as join condition (1):
select
t1.id,
array_agg(
json_build_object('id', t2.id, 'status', t2.status)
) as statuses
from table1 t1
inner join table2 t2 on t1.id=t2.user_id
inner join table3 t3 on t1.id=t3.user_id
and t3.status = 'A12' -- 1.
group by t1.id
Furthermore, if you want to get valid JSON arrays, you should use json_agg() instead of array_agg():
select
t1.id,
json_agg(
json_build_object('id', t2.id, 'status', t2.status)
) as statuses
from table1 t1
inner join table2 t2 on t1.id=t2.user_id
inner join table3 t3 on t1.id=t3.user_id
and t3.status = 'A12'
group by t1.id

Adding fifth join in the table

I have so far written the following mysql query which is joining 4 tables as follows:
SELECT
T3.fault, t4.name
FROM table2 T2
INNER JOIN (
SELECT a.*
FROM table1 a
LEFT JOIN table1 b ON a.item_id = b.item_id AND a.submit_id < b.submit_id
WHERE b.submit_id IS NULL
) T1 ON T1.item_id = T2.item_id
INNER JOIN table3 T3 ON T1.id = T3.run_id
LEFT JOIN table4 T4
ON 3.runname_id = T4.id
order by count(*) desc;
Below is sample Data for table 2 which has item_id as PK
Example query: select * from table2 where item_id = '15907';
item_id host
15907 abc.com
7303 cde.com
7304 abcd.com
7305 cdedf.com
I have now recently added a table table5 which looks as below and has item_id as PK. I want to join table5 with table2 on item_id and want to retrieve value for restoreid also in my final query.
item_id restoreId
15907 12342
7303 12342
7304 14342
7305 14342
How to implement join between table5 and table2 on item_id? My select query should also retrieve T5.restoreId along with T3.fault, t4.name
select your_table.fault,your_table.name,t5.restoreid
from (
SELECT
T3.fault, t4.name,t2.item_id
FROM table2 T2
INNER JOIN (
SELECT a.*
FROM table1 a
LEFT JOIN table1 b ON a.item_id = b.item_id AND a.submit_id < b.submit_id
WHERE b.submit_id IS NULL
) T1 ON T1.item_id = T2.item_id
INNER JOIN table3 T3 ON T1.id = T3.run_id
LEFT JOIN table4 T4
ON 3.runname_id = T4.id
) as your_table left join table5 t5 on your_table.item_id = t5.item_id
SELECT
T3.fault, t4.name, T5.restoreid
FROM table2 T2
INNER JOIN (
SELECT a.*
FROM table1 a
LEFT JOIN table1 b ON a.item_id = b.item_id AND a.submit_id < b.submit_id
WHERE b.submit_id IS NULL
) T1 ON T1.item_id = T2.item_id
INNER JOIN table3 T3 ON T1.id = T3.run_id
LEFT JOIN table4 T4
ON T3.runname_id = T4.id
LEFT JOIN table5 ON T2.item_id = T5.item_id;

MySQL - Where occurs at least 3 times

I have got this query, which works fine:
SELECT t1.*, t2.ip as ip
FROM table1 t1
INNER JOIN table2 t2 ON ( t2.id = t1.t2id )
ORDER BY t1.timestamp DESC
LIMIT 1000
What I would like to do is to:
1) get only those entries where the same ip occurs at least 3 times
2) group the entries by ip
So the result would look like this example:
IP TIMESTAMP
111.111.111.111 1500000000
111.111.111.111 1300000000
111.111.111.111 1100000000
222.222.222.222 1400000000
222.222.222.222 1300000000
222.222.222.222 1200000000
I have tried many approaches and I believe that this one is the closest,
but the result is 0 rows.
SELECT *, COUNT(DISTINCT ip) FROM (
SELECT t1.*, t2.ip as ip
FROM table1 t1
INNER JOIN table2 t2 ON ( t2.id = t1.t2id )
ORDER BY t1.timestamp DESC
LIMIT 1000
) AS tmp_table
GROUP BY ip
HAVING COUNT(DISTINCT ip) > 2
Please can someone shine some light on this?
Try this:
SELECT t1.*, (SELECT DISTINCT t2.ip FROM t2 WHERE t2.id = t1.t2id)
FROM t1
WHERE
(SELECT COUNT(*)
FROM t2
WHERE t2.id = t1.t2id) >= 3
Bacause in the comments has resulted table t2 with more rows for the same IP I change my query as follow:
SELECT t1.*, t2.ip
FROM t1
JOIN t2
ON t2.id = t1.t2id
WHERE
(SELECT COUNT(*)
FROM t2 tt2
WHERE t2.ip = tt2.ip) >= 3
You can see SqlFiddle
SELECT *, COUNT(ip) FROM (
SELECT t1.*, t2.ip as ip
FROM table1 t1
INNER JOIN table2 t2 ON ( t2.id = t1.t2id )
ORDER BY t1.timestamp DESC
LIMIT 1000
) AS tmp_table
GROUP BY ip
HAVING COUNT(ip) > 2
just remove distinct
You have to have the HAVING in the subquery
SELECT t1.*, t2.ip as ip
FROM table1 t1
INNER JOIN table2 t2 ON ( t2.id = t1.t2id )
INNER JOIN
(
SELECT t2.ip
FROM table1 t1
INNER JOIN table1 t2 ON ( t2.id = t2.t2id )
GROUP BY t2.ip
HAVING count(ip) > 2
) t ON t2.ip = t.ip
Try like this;
SELECT t2.ip as ip
FROM table1 t1
INNER JOIN table2 t2 ON ( t2.id = t1.t2id )
where t2.ip IN (SELECT ip FROM (
SELECT t2.ip as ip
FROM table1 t1
INNER JOIN table2 t2 ON ( t2.id = t1.t2id )
) AS tmp_table
GROUP BY ip
HAVING COUNT(*) > 2)
ORDER BY t1.timestamp DESC
LIMIT 1000

Left join query

I have the following query
SELECT table1.*,
table2.status
FROM table1
LEFT JOIN table2 ON table1.transactionid = table2.transactionid
WHERE table2.transactionid IS NULL --Doesn't exist in table2
OR table2.status = 2
It returns me the table1 row if there isn't any row under the same transactionid in table2 or there is a row but it has status = 2 (error)
Now i need to modify it to don't return any table1 rows if there is a row with the same transactionid and status = 1 (completed) in table2
So, there can be multiple error rows but if there is one that is completed then i shouldn't get any result
Thank you
Not exists comes to mind:
SELECT t1.*
FROM table1 t1
WHERE NOT EXISTS (SELECT 1
FROM table2
WHERE t1.transactionid = t2.transactionid AND
t2.status = 1
);
Using 'NOT IN'
SELECT t1.*
FROM table1 t1
WHERE t1.transactionid NOT IN (SELECT t2.transactionid
FROM table2 t2
WHERE t1.transactionid = t2.transactionid AND
t2.status = 1
);
OR USING LEFT JOIN
SELECT t1.*
FROM table1 t1
LEFT JOIN table2 t2
ON t1.transactionid = t2.transactionid
WHERE t2.transactionid IS NULL

Select multiple values from query

I have a query that looks like this:
SELECT T1.ID, T3.Val FROM Table1 as T1
INNER JOIN Table2 as T2 ON T1.ID = T2.ID
INNER JOIN Table3 as T3 ON T2.ID = T3.ID
My problem is that the last Inner Join returns 3 rows and i want to print all of those values like T3.val1, T3.val2, T3.val3
How is that done?
EDIT: Example data:
T3
DataID, DefinitionID, ItemID, UnitID, Val, TS
123 111 4541 45545 0.05 2016-05-07 06:14:07
124 111 5487 69587 0.026 2016-05-07 09:11:01
125 111 3621 12862 0 2016-05-07 10:04:17
This is now my query:
SELECT t1.EventID, group_concat(t3.Val) FROM T1 as t1
INNER JOIN T2 as t2 ON t1.EventID = t2.EventID
INNER JOIN T3 as t3 on t2.DefinitionID = t3.DefinitionID
GROUP BY t3.Val;
And the result is:
EventID group_concat(t3.val)
3 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0........
SELECT T1.ID, GROUP_CONCAT(T3.Val,',') FROM Table1 as T1
INNER JOIN Table2 as T2 ON T1.ID = T2.ID
INNER JOIN Table3 as T3 ON T2.ID = T3.ID
GROUP BY T3.ID
Table1
---------------------
ID
1
Table2
---------------------
ID
1
Table3
---------------------
ID Val
1 A
1 B
1 C
Output
ID Val
1 A,B,C