Select with innerjoin and dynamic update - mysql

I created a query in my magento database to find product the have a "New From" dat but no "New To".
SELECT
catalog_product_entity.entity_id,
catalog_product_entity.sku,
a.value as New_From,
b.value as New_To
FROM `catalog_product_entity`
INNER JOIN catalog_product_entity_datetime as a on a.entity_id = catalog_product_entity.entity_id and a.attribute_id = '93'
INNER JOIN catalog_product_entity_datetime as b on b.entity_id = catalog_product_entity.entity_id and b.attribute_id = '94'
WHERE a.value IS NOT NULL AND b.value IS NULL
Now what I would like to accomplish since it concerns 500+ items to run a UPDATE statement on this query closing "New To" 1 month after having been opened.
Any ideas how to run that?
So to clarify:
Table 1: (catalog_product_entity)
| entity_id | sku |
| --------- | --- |
| 1 | ABC |
| 2 | DEF |
Table 2: (catalog_product_entity_datetime)
| id | entity_id | attribute_id | value |
| --- | --------- | ------------ | ----- |
| 1 | 1 | 93 | 2013-06-12 00:00:00 |
| 2 | 1 | 94 | 2013-07-12 00:00:00 |
| 3 | 1 | 98 | Some other attribute |
| 4 | 2 | 93 | 2014-08-20 00:00:00 |
| 5 | 2 | 94 | NULL | <- This I want updating
| 6 | 2 | 98 | Some other attribute |
I want to update the NULL values in table 2 with the date from that same table + 1 month. My search returns:
| entity -id | sku | New_From | New_To |
| ----------- | --- | ------------------- | ------------------- |
| 2 | DEF | 2014-08-20 00:00:00 | NULL |
So I would like to write the query that updates that field to the New_From + 1 month.
| entity -id | sku | New_From | New_To |
| ----------- | --- | ------------------- | ------------------- |
| 2 | DEF | 2014-08-20 00:00:00 | 2014-09-20 00:00:00 |
In my mind I will end up with something like this: (but this one does not work)
UPDATE catalog_product_entity_datetime
SET value = TIMESTAMP(a.value+300000000)
INNER JOIN catalog_product_entity_datetime as a on a.entity_id = catalog_product_entity_datetime.entity_id and a.attribute_id = '93'
WHERE attribute_id=94

Try this:
UPDATE catalog_product_entity_datetime t1
JOIN catalog_product_entity t2
ON t1.entity_id = t2.entity_id
AND t1.attribute_id = 94
JOIN catalog_product_entity_datetime t3
ON t2.entity_id = t3.entity_id
AND t3.attribute_id = 93
SET t1.value = CASE WHEN t1.value IS NULL THEN date_add(t3.value, interval 1 month)
ELSE t1.value END
;
Demo Here

Related

SQL join tables with conditions to only show Max

I need to join tableA and tableB on UniqueID however I only want to join on the latest Date in tableA with certain Status restrictions (Not in S). I know I need to use the Max functions however I can't get it to work. How do I get the result table below?
I was thinking of something like:
Select
tableA.UniqueID,
MAX(tableA.Date),
tableA.Status,
tableB.Col1
From tableA
Inner join tableB on (tableB.UniqueID = tableA.UniqueID and tableA.Status = 'A')`
tableA:
| UniqueID | Date | Status |
| -------- | ------------------- |--------|
| 123 | 2015-07-05 00:00:00 | S |
| 123 | 2015-07-06 00:00:00 | S |
| 123 | 2015-07-07 00:00:00 | A |
and tableB:
| UniqueID | Col1 |
| -------- | - |
| 123 | X |
| 125 | Y |
| 126 | Z |
Result table:
| UniqueID | Date | Status | Col1|
| -------- | ------------------- |--------|---- |
| 123 | 2015-07-07 00:00:00 | A | X |
This is one of the ways -
select
t_a.*, t_b.*
from
table_b t_b
join
(
select
uniqueid, date, status,
rank() over (partition by uniqueid order by date desc ) rank_
from
table_a
) t_a on t_b.uniqueid = t_a.uniqueid
where
t_a.rank_ = 1
;
fiddle url : (https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=06660177b6c116a811218863ce428985)

MySql Left Join records where is null with handling validUntil Row

How to select all addons which a specific user has not buyed or are no longer valid?
Assuming currentdate is 2017-03-02 17:00:00
Table1 (users):
+-----------+----------+
| id | username |
+-----------+----------+
| 1 | Walter |
| 2 | Hank |
| 3 | John |
+-----------+----------+
Table2 (buyLog):
+-----------+----------+------------+---------------------+
| id | idUsers | idItems | validUntil |
+-----------+----------+------------+---------------------+
| 1 | 1 | 1 | 2016-03-02 14:15:47 |
| 2 | 1 | 1 | 2018-03-02 14:15:47 |
| 3 | 1 | 2 | 2016-03-02 14:15:47 |
| 4 | 2 | 1 | 2018-03-02 14:15:47 |
+-----------+----------+------------+---------------------+
Table3 (addons):
+-----------+----------+
| id | name |
+-----------+----------+
| 1 | Foo |
| 2 | Bar |
| 3 | Lorem |
+-----------+----------+
Expected output for user with id 1 should be:
+-----------+----------+
| id | name |
+-----------+----------+
| 2 | Bar |
| 3 | Lorem |
+-----------+----------+
See SQL Fiddle here: http://sqlfiddle.com/#!9/16356
Where I have the most problems is to handle the validUntil in the leftJoin.
I think I have to group by during the left join to tread only the most recent validUntil record. Maybe using max(validUntil)?
This code will work
http://sqlfiddle.com/#!9/16356/1/0
SELECT
C.ID AS 'ID',
C.NAME AS 'NAME'
FROM
(SELECT
A.id AS 'ID',A.name AS 'NAME',
CASE
WHEN B.YY > '2017-03-02 17:00:00' THEN 0
ELSE 1 END AS 'Tag'
FROM
addons AS A
LEFT JOIN
(SELECT idItems AS 'XX', MAX(validUntil) AS 'YY'
FROM
buyLog
WHERE idUsers = 1 GROUP BY 1) AS B
ON
A.id = B.XX) AS C
WHERE
C.Tag = 1
My sense is that neither your explanation nor your data set and desired result are adequate to the task of explaining the problem. The following query produces the desired result, but perhaps that's just coincidence...
SELECT a.*
FROM addons a
LEFT
JOIN buylog b
ON b.iditems = a.id
AND b.validuntil > NOW()
LEFT
JOIN users u
ON u.id = b.idusers
AND u.id = 1
WHERE b.validuntil IS NULL
AND u.id IS NULL;

SQL server JOIN query not working

Hi I have doubt in sql server
dept
+---------+--------+
| deptkey | deptno |
+---------+--------+
| 1 | 100 |
| 2 | 101 |
| 3 | -1 |
+---------+--------+
loc
+--------+-------+
| lockey | locid |
+--------+-------+
| 1 | 200 |
| 2 | 201 |
| 3 | -1 |
+--------+-------+
trans
+----+--------+-------+------+
| id | deptno | locid | Name |
+----+--------+-------+------+
| 1 | 100 | 201 | abc |
| 2 | 101 | 203 | def |
| 3 | 103 | 200 | rav |
| 4 | 105 | 204 | jai |
| 1 | 101 | 200 | kal |
| 4 | 100 | 206 | lo |
+----+--------+-------+------+
here tran deptno= dept.deptno then corresponding key values bring if not match then we need to unmatched deptno assign -1 and corresponding key need to retrive
similar tran locid=loc.locid
based on above tables I want output like below
+----+------+---------+--------+
| id | Name | deptkey | lockey |
+----+------+---------+--------+
| 1 | abc | 1 | 2 |
| 2 | def | 2 | 3 |
| 3 | rav | 3 | 1 |
| 4 | jai | 3 | 3 |
| 1 | kal | 2 | 1 |
| 4 | lo | 1 | 3 |
+----+------+---------+--------+
I tried like below query
SELECT a.[id],a.name ,b.deptkey,c.lockey
FROM [trans] a left join dept b on a.deptno=b.deptno
left join loc c on a.locid=c.locid
above query not given expected result can you please tell me how to write query to achive this task in sql server
SELECT a.[id],a.name ,
(CASE WHEN b.deptkey IS NULL THEN (select deptkey from DEPT WHERE DeptNo = -1)
ELSE b.deptkey END) AS 'deptkey',
(CASE WHEN c.lockey IS NULL THEN (select LocKey from LOC WHERE LocId = -1)
ELSE c.lockey END) AS 'lockey '
FROM [trans] a left join dept b on a.deptno=b.deptno
left join loc c on a.locid=c.locid
http://www.sqlfiddle.com/#!3/389463/2
SELECT a.[id],a.name ,b.deptkey,c.lockey
FROM [trans] a left join dept b on isnull(a.deptno,-1)=isnull(b.deptno,-1)
left join loc c on a.locid=c.locid
try with this...
SELECT
a.[id]
, a.name
, ISNULL(b.deptkey,-1) AS [deptkey]
, ISNULL(b.lockey,-1) AS [lockey]
FROM [trans] a
left join dept b
on a.deptno = b.deptno
left join loc c
on a.locid = c.locid
When the value is not found ISNULL, change the result to -1 instead of NULL. You can just change the -1 with any default value you prefer as unmatched.
OR if you want a query driven default value (get the last record as the default value). You can change your script as presented below.
SELECT
a.[id]
, a.name
, ISNULL(b.deptkey,(SELECT TOP 1 deptno from dept ORDER BY deptkey DESC)) AS [deptkey]
, ISNULL(b.lockey,(SELECT TOP 1 locid from loc ORDER BY lockey DESC)) AS [lockey]
FROM [trans] a
left join dept b
on a.deptno = b.deptno
left join loc c
on a.locid = c.locid

How to fetch data from two tables using mysql query with some conditions applied to the second table?

I want to generate a result from a MySql query with below requirement.
Table 1 :
---------------
| nid | type |
---------------
| 1 | forum |
| 2 | forum |
| 3 | forum |
| 4 | forum |
---------------
Table 2
-----------------------
| nid | cid | created |
-----------------------
| 1 | 32 | 123456 |
| 2 | 65 | 123457 |
| 4 | 67 | 123458 |
| 1 | 61 | 123491 |
| 1 | 78 | 123497 |
| 2 | 23 | 123498 |
| 1 | 12 | 123698 |
| 4 | 54 | 132365 |
| 4 | 81 | 135698 |
| 1 | 30 | 168965 |
-----------------------
Now i require result like below. (Condition : I need the nid from first table, smallest cid for the corresponding nid in second table WHERE type = 'forum')
--------------
| nid | cid |
--------------
| 1 | 12 |
| 2 | 23 |
| 4 | 67 |
--------------
You can try this
SELECT tbl1.nid,
min(tbl2.cid) as cid
FROM table1 tbl1
INNER JOIN table2 tbl2 ON tbl1.nid=tbl2.nid
GROUP BY tbl2.nid;
SQL Fiddle
Try this
SELECT t1.nid,
min(t2.cid) as cid
FROM table1 t1
INNER JOIN table2 t2 ON t1.nid=t2.nid
GROUP BY t2.nid;
This could also work
select nid, min(cid) cid
from table2
group by nid
The above queries are have issues in group by clause. Kindly check this query.
SELECT t1.NID, MIN(t2.CID) AS cis from
TAB1 t1 inner join TAB2 t2 on t1.nid = t2.nid
group by t1.nid

MySQL - How to update atable based on an internal ordering of the table

If I make a selection from my MySQL table like:
SELECT * FROM mytable ORDER BY country_id, category
I get the following table:
+------------+----------+-------+
| country_id | category | order |
+------------+----------+-------+
| 1 | A | 0 |
| 1 | B | 0 |
| 1 | F | 0 |
| 3 | A | 0 |
| 3 | C | 0 |
| 5 | B | 0 |
| 5 | L | 0 |
| 5 | P | 0 |
+------------+----------+-------+
What I would like to do is update the order column so that the value of that column is the order of that row for it's country_id. In other words the final table should look like this:
+------------+----------+-------+
| country_id | category | order |
+------------+----------+-------+
| 1 | A | 1 |
| 1 | B | 2 |
| 1 | F | 3 |
| 3 | A | 1 |
| 3 | C | 2 |
| 5 | B | 1 |
| 5 | L | 2 |
| 5 | P | 3 |
+------------+----------+-------+
If I use the original query given at the top in a subquery, that would give me the correct order but I can't figure out how to iterate through the table and suspect I thinking about it wrongly.
How can I get this result?
Many thanks
Try to use this query -
UPDATE mytable t1
JOIN (
SELECT t1.country_id, t1.category, COUNT(*) `order`
FROM mytable t1
LEFT JOIN mytable t2
ON t2.country_id = t1.country_id AND t2.category <= t1.category
GROUP BY
t1.country_id, t1.category
) t2
ON t1.country_id = t2.country_id AND t1.category = t2.category
SET t1.`order` = t2.`order`
As an aside note, you can remove order field from the table because this can calculated this on the fly.