How to insert the current_timestamp for newly inserted rows - postgresql-9.5

I need to insert the data with timestamp daily three times. I need to insert current_timestamp in null values in the time column
update tablename
set time = CURRENT_TIMESTAMP
WHERE time = null
name | marks | time
---------+-------+----------------------------
GANESH | 80 | 2019-01-06 05:03:24.171124
GANESH | 90 | 2019-01-06 05:03:24.171124
GANESH | 100 | 2019-01-06 05:03:24.171124
SURESH | 10 | 2019-01-06 05:03:24.171124
SURESH | 20 | 2019-01-06 05:03:24.171124
SURESH | 30 | 2019-01-06 05:03:24.171124
RAKESH | 90 | 2019-01-06 05:03:24.171124
Vishnu | 900 | 2019-01-06 05:03:24.171124
VITAL | 100 | 2019-01-06 05:03:24.171124
SEENU | 100 | 2019-01-06 05:03:24.171124
VITAL1 | 100 |
VITAL12 | 100 |
VITAL13 | 100 |
raj | |
raj1 | |
raj2 | |
I am expecting to insert the current_timestamp in null places
name | marks | time
---------+-------+----------------------------
GANESH | 80 | 2019-01-06 05:03:24.171124
GANESH | 90 | 2019-01-06 05:03:24.171124
GANESH | 100 | 2019-01-06 05:03:24.171124
SURESH | 10 | 2019-01-06 05:03:24.171124
SURESH | 20 | 2019-01-06 05:03:24.171124
SURESH | 30 | 2019-01-06 05:03:24.171124
RAKESH | 90 | 2019-01-06 05:03:24.171124
Vishnu | 900 | 2019-01-06 05:03:24.171124
VITAL | 100 | 2019-01-06 05:03:24.171124
SEENU | 100 | 2019-01-06 05:03:24.171124
VITAL1 | 100 | 2019-01-07 11:03:24.171124
VITAL12 | 100 | 2019-01-07 11:03:24.171124
VITAL13 | 100 | 2019-01-07 11:03:24.171124
raj | | 2019-01-07 11:03:24.171124
raj1 | | 2019-01-07 11:03:24.171124
raj2 | |2019-01-07 11:03:24.171124

If you want to compare a column against NULL, you need to use the IS NULL or IS NOT NULL operators. So, the following should work:
UPDATE tablename
SET time = CURRENT_TIMESTAMP
WHERE time IS NULL;
This question is almost a typo question, except that understanding what NULL semantically means in SQL is more than a typo issue. The NULL value itself means "not known," so it makes no sense to use = to check it.

Related

How to fill NULL value using min-max in SQL Server?

I want to get front value and back value using min-max comparing.
Here is my sample table.
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=322aafeb7970e25f9a85d0cd2f6c00d6
For example, this is temp01 table.
I want to get start&end NULL value in temp01.
So, I fill
price = [NULL, NULL, 13000]
to
price = [12000, 12000, 13000]
Because the 12000 is minimum value in [230, 1]. And I fill end NULL is filled maximum value in [cat01, cat02] group
| SEQ | cat01 | cat02 | dt_day | price |
+-----+-------+-------+------------+-------+
| 1 | 230 | 1 | 2019-01-01 | NULL |
| 2 | 230 | 1 | 2019-01-02 | NULL |
| 3 | 230 | 1 | 2019-01-03 | 13000 |
...
| 11 | 230 | 1 | 2019-01-11 | NULL |
| 12 | 230 | 1 | 2019-01-12 | NULL |
| 1 | 230 | 2 | 2019-01-01 | NULL |
| 2 | 230 | 2 | 2019-01-02 | NULL |
| 3 | 230 | 2 | 2019-01-03 | 12000 |
...
| 12 | 230 | 2 | 2019-01-11 | NULL |
| 13 | 230 | 2 | 2019-01-12 | NULL |
[result]
| SEQ | cat01 | cat02 | dt_day | price |
+-----+-------+-------+------------+-------+
| 1 | 230 | 1 | 2019-01-01 | 12000 | --START
| 2 | 230 | 1 | 2019-01-02 | 12000 |
| 3 | 230 | 1 | 2019-01-03 | 13000 |
| 4 | 230 | 1 | 2019-01-04 | 12000 |
| 5 | 230 | 1 | 2019-01-05 | NULL |
| 6 | 230 | 1 | 2019-01-06 | NULL |
| 7 | 230 | 1 | 2019-01-07 | 19000 |
| 8 | 230 | 1 | 2019-01-08 | 20000 |
| 9 | 230 | 1 | 2019-01-09 | 21500 |
| 10 | 230 | 1 | 2019-01-10 | 21500 |
| 11 | 230 | 1 | 2019-01-11 | 21500 |
| 12 | 230 | 1 | 2019-01-12 | 21500 |
| 13 | 230 | 1 | 2019-01-13 | 21500 | --END
| 1 | 230 | 2 | 2019-01-01 | 12000 | --START
| 2 | 230 | 2 | 2019-01-02 | 12000 |
| 3 | 230 | 2 | 2019-01-03 | 12000 |
| 4 | 230 | 2 | 2019-01-04 | 17000 |
| 5 | 230 | 2 | 2019-01-05 | 22000 |
| 6 | 230 | 2 | 2019-01-06 | NULL |
| 7 | 230 | 2 | 2019-01-07 | 23000 |
| 8 | 230 | 2 | 2019-01-08 | 23200 |
| 9 | 230 | 2 | 2019-01-09 | NULL |
| 10 | 230 | 2 | 2019-01-10 | 24000 |
| 11 | 230 | 2 | 2019-01-11 | 24000 |
| 12 | 230 | 2 | 2019-01-12 | 24000 |
| 13 | 230 | 2 | 2019-01-13 | 24000 | --END
Please, let me know what a good way to fill NULL using linear relationships.
find the min() and max() for the price GROUP BY cat01, cat02.
Also find the min and max seq for the row where price is not null
after that it is just simply inner join to your table and update where price is null
with val as
(
select cat01, cat02,
min_price = min(price),
max_price = max(price),
min_seq = min(case when price is not null then seq end),
max_seq = max(case when price is not null then seq end)
from temp01
group by cat01, cat02
)
update t
set price = case when t.seq < v.min_seq then min_price
when t.seq > v.max_seq then max_price
end
FROM temp01 t
inner join val v on t.cat01 = v.cat01
and t.cat02 = v.cat02
where t.price is null
dbfiddle
EDIT : returning the price as a new column in SELECT query
with val as
(
select cat01, cat02, min_price = min(price), max_price = max(price),
min_seq = min(case when price is not null then seq end),
max_seq = max(case when price is not null then seq end)
from temp01
group by cat01, cat02
)
select t.*,
new_price = coalesce(t.price,
case when t.seq < v.min_seq then min_price
when t.seq > v.max_seq then max_price
end)
FROM temp01 t
left join val v on t.cat01 = v.cat01
and t.cat02 = v.cat02
Updated dbfiddle

select Data for only week days and calculate difference

I am working on an sql query to calculate MTBF
I have following set of data
+-----+-------------------------+------+
| ID | DateTime | Sec |
+-----+-------------------------+------+
| 101 | 2019-07-22 09:10:10.000 | 900 |
| 100 | 2019-07-22 08:45:00.000 | 900 |
| 99 | 2019-07-22 08:30:00.000 | 800 |
| 98 | 2019-07-22 08:15:00.000 | 800 |
| 97 | 2019-07-22 07:10:10.000 | 600 |
| 96 | 2019-07-22 06:50:00.000 | 600 |
| 95 | 2019-07-22 06:40:00.000 | 400 |
| 94 | 2019-07-21 15:40:00.000 | 720 |
| 93 | 2019-07-21 13:25:00.000 | 400 |
| 92 | 2019-07-21 10:43:10.000 | 900 |
| 91 | 2019-07-20 07:30:00.000 | 800 |
| 90 | 2019-07-19 20:40:10.000 | 900 |
| 89 | 2019-07-19 18:30:30.000 | 700 |
| 88 | 2019-07-19 17:50:00.000 | 400 |
| 87 | 2019-07-19 16:40:00.000 | 400 |
| 86 | 2019-07-19 15:20:25.000 | 1000 |
| 85 | 2019-07-19 14:50:20.000 | 900 |
| 84 | 2019-07-19 14:30:00.000 | 8000 |
| 83 | 2019-07-19 14:10:10.000 | 600 |
| 82 | 2019-07-19 13:59:00.000 | 200 |
| 81 | 2019-07-19 13:50:40.000 | 300 |
| 80 | 2019-07-19 13:40:00.000 | 400 |
+-----+-------------------------+------+
I want to calculate the difference between the ID 101 and 100, and than between 100 and 99 and so on.
But here is difficult part
I don't want to calculate the difference between for weekend dates in this case for a date 20-07-2019 and 21-07-2019.
I always want to calculate the difference only for week days.
so for given Sample data the output has to be following.
+-----+-------------------------+------+---------+
| ID | DateTime | Sec | Diff |
+-----+-------------------------+------+---------+
| 101 | 2019-07-22 09:10:10.000 | 900 | Null |
| 100 | 2019-07-22 08:45:00.000 | 900 | 0:25:10 |
| 99 | 2019-07-22 08:30:00.000 | 800 | 0:15:00 |
| 98 | 2019-07-22 08:15:00.000 | 800 | 0:15:00 |
| 97 | 2019-07-22 07:10:10.000 | 600 | 1:04:50 |
| 96 | 2019-07-22 06:50:00.000 | 600 | 0:20:10 |
| 95 | 2019-07-22 06:40:00.000 | 400 | 0:10:00 |
| 94 | 2019-07-21 15:40:00.000 | 720 | Null |
| 93 | 2019-07-21 13:25:00.000 | 400 | Null |
| 92 | 2019-07-21 10:43:10.000 | 900 | Null |
| 91 | 2019-07-20 07:30:00.000 | 800 | Null |
| 90 | 2019-07-19 20:40:10.000 | 900 | Null |
| 89 | 2019-07-19 18:30:30.000 | 700 | 2:09:40 |
| 88 | 2019-07-19 17:50:00.000 | 400 | 0:40:30 |
| 87 | 2019-07-19 16:40:00.000 | 400 | 1:10:00 |
| 86 | 2019-07-19 15:20:25.000 | 1000 | 1:19:35 |
| 85 | 2019-07-19 14:50:20.000 | 900 | 0:30:05 |
| 84 | 2019-07-19 14:30:00.000 | 8000 | 0:20:20 |
| 83 | 2019-07-19 14:10:10.000 | 600 | 0:19:50 |
| 82 | 2019-07-19 13:59:00.000 | 200 | 0:11:10 |
| 81 | 2019-07-19 13:50:40.000 | 300 | 0:08:20 |
| 80 | 2019-07-19 13:40:00.000 | 400 | 0:10:40 |
+-----+-------------------------+------+---------+
after that i wan to sum all the difference and divide by number (count) of id in week days.
Below is the query i have tried until now
SELECT *, DATEDIFF( SECOND, DateTime, LEAD(DateTime) OVER (ORDER BY [ID])) AS [diff] FROM [Stoerungen] where [DateTime] between '20190719 00:00:00.000' and '20190722 23:59:00.000' and ((DATEPART(dw, DateTime) + ##DATEFIRST) % 7) NOT IN (0, 1) order by [ID] OFFSET 0 ROWS
I am able to exclude the weekend data but this query makes a difference from last Friday to next Monday so I have wrong data.
As you don't want exclude non-week days but only set Diff to null, move this condition to CASE expression
SELECT *
, (case When (((DATEPART(dw, DateTime) + ##DATEFIRST) % 7) NOT IN (0, 1))
then DATEDIFF( SECOND, DateTime, LEAD(DateTime) OVER (ORDER BY [ID]))
else null
end) AS [diff]
FROM [Stoerungen]
WHERE [DateTime] between '20190719 00:00:00.000' and '20190722 23:59:00.000'
ORDER BY [ID]
OFFSET 0 ROWS

How to update column with average weekly value for each day in sql

I have the following table. I insert a column named WeekValue, I want to fill the weekvalue column with the weekly average value of impressionCnt of the same category for each row.
Like:
+-------------------------+----------+---------------+--------------+
| Date | category | impressioncnt | weekAverage |
+-------------------------+----------+---------------+--------------+
| 2014-02-06 00:00:00.000 | a | 123 | 100 |
| 2014-02-06 00:00:00.000 | b | 121 | 200 |
| 2014-02-06 00:00:00.000 | c | 99 | 300 |
| 2014-02-07 00:00:00.000 | a | 33 | 100 |
| 2014-02-07 00:00:00.000 | b | 456 | 200 |
| 2014-02-07 00:00:00.000 | c | 54 | 300 |
| 2014-02-08 00:00:00.000 | a | 765 | 100 |
| 2014-02-08 00:00:00.000 | b | 78 | 200 |
| 2014-02-08 00:00:00.000 | c | 12 | 300 |
| ..... | | | |
| 2014-03-01 00:00:00.000 | a | 123 | 111 |
| 2014-03-01 00:00:00.000 | b | 121 | 222 |
| 2014-03-01 00:00:00.000 | c | 99 | 333 |
| 2014-03-02 00:00:00.000 | a | 33 | 111 |
| 2014-03-02 00:00:00.000 | b | 456 | 222 |
| 2014-03-02 00:00:00.000 | c | 54 | 333 |
| 2014-03-03 00:00:00.000 | a | 765 | 111 |
| 2014-03-03 00:00:00.000 | b | 78 | 222 |
| 2014-03-03 00:00:00.000 | c | 12 | 333 |
+-------------------------+----------+---------------+--------------+
I tried
update [dbo].[RetailTS]
set Week = datepart(day, dateDiff(day, 0, [Date])/7 *7)/7 +1
To get the week numbers then try to group by the week week number and date and category, but this seems isn't correct. How do I write the SQL query? Thanks!
Given that you may be adding more data in the future, thus requiring another update, you might want to just select out the weekly averages:
SELECT
Date,
category,
impressioncnt,
AVG(impressioncnt) OVER
(PARTITION BY category, DATEDIFF(d, 0, Date) / 7) AS weekAverage
FROM RetailTS
ORDER BY
Date, category;

update a value column of a row based in another value of row

I have a historical table with data as bellow :
In my case the product id (110,111,112) had changed the price that way i have the same product with the value of the product_updateDate also sometimes i can have the same duplicate data with no information changed
+------+------------+--------------+---------------+-----------------------------+-------------------------+-------------------------+----------------+
| id | product_id | product_name | product_Price | product_addDate | product_UpdateDate | Insertdate_DB | Updatedate_DB |
+------+------------+--------------+---------------+-----------------------------+-------------------------+-------------------------+----------------+
| 1 | 110 | DELL | 1000 | 2017-03-01 08:00:00.000 | NULL | 2017-03-06 10:00:00.000 | NULL |
| 2 | 111 | HP | 900 | 2017-03-01 08:00:00.000 | NULL | 2017-03-06 10:00:00.000 | NULL |
| 3 | 112 | Mac | 1300 | 2017-03-01 08:00:00.000 | NULL | 2017-03-06 10:00:00.000 | NULL |
| 4 | 113 | Lenovo | 950 | 2017-03-01 08:00:00.000 | NULL | 2017-03-06 10:00:00.000 | NULL |
| 5 | 110 | DELL | 900 | 2017-03-04 08:00:00.000 | 2017-03-04 08:00:00.000 | 2017-03-07 10:00:00.000 | NULL |
| 6 | 111 | HP | 800 | 2017-03-04 08:00:00.000 | 2017-03-04 08:00:00.000 | 2017-03-07 10:00:00.000 | NULL |
| 7 | 112 | Mac | 120 | 2017-03-04 08:00:00.000 | 2017-03-04 08:00:00.000 | 2017-03-07 10:00:00.000 | NULL |
+------+------------+--------------+---------------+-----------------------------+-------------------------+-------------------------+----------------+
What i want is doing an Update Query to get the result as bellow:
+----+------------+--------------+---------------+-------------------------+-------------------------+-------------------------+---------------+
| id | product_id | product_name | product_Price | product_addDate | product_UpdateDate | Insertdate_DB | Updatedate_DB |
+----+------------+--------------+---------------+-------------------------+-------------------------+-------------------------+---------------+
| 1 | 110 | DELL | 1000 | 2017-03-01 08:00:00.000 | 2017-03-04 08:00:00.000 | 2017-03-06 10:00:00.000 | GETDATE() |
| 2 | 111 | HP | 900 | 2017-03-01 08:00:00.000 | 2017-03-04 08:00:00.000 | 2017-03-06 10:00:00.000 | GETDATE() |
| 3 | 112 | Mac | 1300 | 2017-03-01 08:00:00.000 | 2017-03-04 08:00:00.000 | 2017-03-06 10:00:00.000 | GETDATE() |
| 4 | 113 | Lenovo | 950 | 2017-03-01 08:00:00.000 | NULL | 2017-03-06 10:00:00.000 | NULL |
| 5 | 110 | DELL | 900 | 2017-03-04 08:00:00.000 | NULL | 2017-03-07 10:00:00.000 | NULL |
| 6 | 111 | HP | 800 | 2017-03-04 08:00:00.000 | NULL | 2017-03-07 10:00:00.000 | NULL |
| 7 | 112 | Mac | 120 | 2017-03-04 08:00:00.000 | NULL | 2017-03-07 10:00:00.000 | NULL |
+----+------------+--------------+---------------+-------------------------+-------------------------+-------------------------+---------------+
The query as bellow can update the product_UpdateDate
update tablename
set product_UpdateDate = case when tablename.product_UpdateDate is null
then t.product_UpdateDate
else null end
from tablename
join tablename t
on tablename.product_id = t.product_id
and t.ID <> tablename.id `
But also i want to change the Updatedate_DB with the GETDATE() value when i try to do update this column all rows have the value GETDATE() but i want change only the rows that the value have change
Thanks for help
I think row_number() might be a simpler method. The logic is hard to follow, but the following should result in the data in your question:
with toupdate as (
select t.*,
row_number() over (partition by product_id order by id) as seqnum,
count(*) over (partition by product_id) as cnt
from t
)
update toupdate
set product_UpdateDate = (case when seqnum = 1 then product_addDate end),
Updatedate_DB = (case when seqnum = 1 then getdate() end)
where cnt > 1;

Will Inner join allow duplicates?

if join two tables using inner join method will it return duplicate values ?
Yes, if there are duplicate values.
If you have CUSTOMERS table:
+----+----------+-----+-----------+----------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Ramesh | 32 | Ahmedabad | 2000.00 |
| 2 | Khilan | 25 | Delhi | 1500.00 |
| 3 | kaushik | 23 | Kota | 2000.00 |
| 4 | Chaitali | 25 | Mumbai | 6500.00 |
| 5 | Hardik | 27 | Bhopal | 8500.00 |
| 6 | Komal | 22 | MP | 4500.00 |
| 7 | Muffy | 24 | Indore | 10000.00 |
+----+----------+-----+-----------+----------+
and ORDERS table as follows:
+-----+---------------------+-------------+--------+
| OID | DATE | CUSTOMER_ID | AMOUNT |
+-----+---------------------+-------------+--------+
| 102 | 2009-10-08 00:00:00 | 3 | 3000 |
| 100 | 2009-10-08 00:00:00 | 3 | 1500 |
| 101 | 2009-11-20 00:00:00 | 2 | 1560 |
| 103 | 2008-05-20 00:00:00 | 4 | 2060 |
+-----+---------------------+-------------+--------+
Then inner join will give result:
SELECT ID, NAME, AMOUNT, DATE
FROM CUSTOMERS
INNER JOIN ORDERS
ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID;
This would produce the following result:
+----+----------+--------+---------------------+
| ID | NAME | AMOUNT | DATE |
+----+----------+--------+---------------------+
| 3 | kaushik | 3000 | 2009-10-08 00:00:00 |
| 3 | kaushik | 1500 | 2009-10-08 00:00:00 |
| 2 | Khilan | 1560 | 2009-11-20 00:00:00 |
| 4 | Chaitali | 2060 | 2008-05-20 00:00:00 |
+----+----------+--------+---------------------+
Here is an example with duplicate rows in both tables.
select * from customers;
id | name | age | address
----+-------------+-----+-----------
1 | Ramesh | 32 | Ahmedabad
2 | Khilan | 25 | Delhi
3 | kaushik | 23 | Kota <-- id 3 "kaushik"
3 | kaushik_two | 23 | Ahmedabad <-- appears twice
4 | Chaitali | 25 | Mumbai
5 | Hardik | 27 | Bhopal
6 | Komal | 22 | MP
7 | Muffy | 24 | Indore
(8 rows)
select * from orders;
oid | date | customer_id | amount
-----+---------------------+-------------+--------
102 | 2009-10-08 00:00:00 | 3 | 3000 <-- reference to customer 3
100 | 2009-10-08 00:00:00 | 3 | 1500 <-- also appears twice
101 | 2009-11-20 00:00:00 | 2 | 1560
103 | 2008-05-20 00:00:00 | 4 | 2060
104 | 2022-01-01 00:00:00 | 100 | 3900
(5 rows)
Inner Join
Produces duplicated rows for "kaushik" and "kaushik_two".
select id, name, amount, date
from customers
inner join orders on customers.id = orders.customer_id;
id | name | amount | date
----+-------------+--------+---------------------
2 | Khilan | 1560 | 2009-11-20 00:00:00
3 | kaushik | 1500 | 2009-10-08 00:00:00 <-- first pair
3 | kaushik | 3000 | 2009-10-08 00:00:00
3 | kaushik_two | 1500 | 2009-10-08 00:00:00 <-- second pair
3 | kaushik_two | 3000 | 2009-10-08 00:00:00
4 | Chaitali | 2060 | 2008-05-20 00:00:00
(6 rows)