select only projects where modified date in log_table is from the last 7 days in Sybase - sybase

I'm having a project table with no modify date and a logtable with changes on all tables. In the logtable you can have more than 1 record for 1 project (every time you change something a line is written in the logtable. I was trying to create a select query to have only the projects that are created/updated in the last 7 days.
Something is wrong in my query because I receive:
'derived table Log1 has no name for column 2' SQLCODE=-163
My code:
select pr.projectid,
pr.projecttitle
from project pr
inner
join (select row_ID,
max(date_action)
from logtable_data
group by row_ID
having table_name = 'PROJECT'
and max(date_action) > dateadd(day,-7,convert(Date, getdate(), 365))
) Log1
on pr.projectid = Log1.row_ID
-- table_name = 'PROJECT' is for only have the changes of table 'PROJECT' from the logtable

Your subquery is being used in a join clause so it's also referred to as a derived table.
A derived table must have a name for each of the columns/expressions in the select list.
The second column/expression - max(date_action) - does not have a name hence the error message.
A couple other issues:
table_name = 'PROJECT' should be supplied as a where clause
getdate() returns a date so there's no need to convert its results to date, ie, the convert(Date,...) is unnecessary. [NOTE: I'm also assuming the date_action column
has a data type of date or datetime]
Pulling this all together:
select pr.projectid,
pr.projecttitle
from project pr
inner
join (select row_ID,
max(date_action) as max_action_date -- 'as' clause used to name column
from logtable_data
where table_name = 'PROJECT' -- limit data selection
group by row_ID
having max(date_action) > dateadd(day,-7,getdate())
) Log1
on pr.projectid = Log1.row_ID

Related

SQL Server Query regarding to find all tables with Date when Last record updated Or Inserted

I need to find all the tables order by date in descending order of last updated or inserted rows. Is there any query regarding this?
I am trying with below query but it's giving me only schema updated tables. But I think modify_date is related to schema only.
SELECT
[name] AS [UserTableName]
, create_date AS [CreatedDate]
, modify_date AS [ModifiedDate]
FROM sys.objects
WHERE [type] = 'U' --to only display ‘USER_TABLE’
ORDER BY 3 DESC

Update latest record with previous record values

I have a table called Audits that has a CompanyId, Date, AuditNumber field, each Company can have many audits and the AuditNumber field keeps track of how many audits said company has.
I'm trying to update all latest audit records date with it's previous date + 5 years, so say CompanyId 12345 has 3 audits, I want to update the 3rd audit (3rd audit being the latest one) records date with the 2nd audit records date + 5 years into the future, etc... basically doing this to all the latest records.
What I've got so far is trying to use a while loop to do this but I'm pretty stuck as it's not exactly doing what I want it to...
DECLARE #counter INT = 1;
WHILE(#counter <= (SELECT COUNT(*) FROM Audits WHERE AuditNumber > 1)
BEGIN
UPDATE Audits
SET Date = CASE
WHEN AuditNumber > 1 THEN (SELECT TOP 1 DATEADD(YEAR, 5, Date) FROM Audits WHERE AuditNumber < (SELECT(MAX(AuditNumber) FROM Audits))
END
WHERE AuditNumber > 1
SET #counter = #counter + 1
END
I'm no expert on SQL, but this just updates the Date with the first previous date it can find due to the SELECT TOP(1) but if I don't put that TOP(1) the subquery returns more than 1 record so it complains.
Any help would be appreciated.
Thanks!
No need for a procedure and a loop. I would recommend window functions and an updatable cte for this:
with cte as (
select date,
row_number() over(partition by company order by auditnumber desc) rn,
lag(date) over(partition by company order by auditnumber) lag_date
from audits
)
update cte
set date = dateadd(year, 5, lag_date)
where rn = 1 and lag_date is not null
The common table expression ranks records having the same company by descending audit number, and retrieves the date of the previous audit. The outer query filters on the top record per group, and updates the date to 5 years after the previous date.
You did not tell what to do when a company has just one audit. I added a condition to no update those rows, if any.
You must add row_number to you result_tbl first then join result_tbl with self ON
Al.CompanyId=A2.CompanyId AND Al.IND=1 AND A2.IND=2, now you have latest record and previous record in one record, and you can update original table
WITH A AS
(
SELECT *,ROW_NUMBER(PARTITION BY CompanyId ORDER BY AuditNumber DESC) IND FROM Audits
),B AS
(
SELECT Al.CompanyId,A1.AuditNumber,A2.[DATE] FROM A A1 INNER JOIN A A2 ON Al.CompanyId=A2.CompanyId AND Al.IND=1 AND A2.IND=2
)UPDATE _Audits SET _Audits.[Date]= DATEADD(YEAR,5,B.[DATE]) FROM
B LEFT JOIN Audits _Audits ON B.CompanyId=_Audits.CompanyId AND B.AuditNumber=_Audits.AuditNumber

T-SQL: GROUP BY, but while keeping a non-grouped column (or re-joining it)?

I'm on SQL Server 2008, and having trouble querying an audit table the way I want to.
The table shows every time a new ID comes in, as well as every time an IDs Type changes
Record # ID Type Date
1 ae08k M 2017-01-02:12:03
2 liei0 A 2017-01-02:12:04
3 ae08k C 2017-01-02:13:05
4 we808 A 2017-01-03:20:05
I'd kinda like to produce a snapshot of the status for each ID, at a certain date. My thought was something like this:
SELECT
ID
,max(date) AS Max
FROM
Table
WHERE
Date < 'whatever-my-cutoff-date-is-here'
GROUP BY
ID
But that loses the Type column. If I add in the type column to my GROUP BY, then I'd get get duplicate rows per ID naturally, for all the types it had before the date.
So I was thinking of running a second version of the table (via a common table expression), and left joining that in to get the Type.
On my query above, all I have to join to are the ID & Date. Somehow if the dates are too close together, I end up with duplicate results (like say above, ae08k would show up once for each Type). That or I'm just super confused.
Basically all I ever do in SQL are left joins, group bys, and common table expressions (to then left join). What am I missing that I'd need in this situation...?
Use row_number()
select *
from ( select *
, row_number() over (partition by id order by date desc) as rn
from table
WHERE Date < 'whatever-my-cutoff-date-is-here'
) tt
where tt.rn = 1
I'd kinda like know how many IDs are of each type, at a certain date.
Well, for that you use COUNT and GROUP BY on Type:
SELECT Type, COUNT(ID)
FROM Table
WHERE Date < 'whatever-your-cutoff-date-is-here'
GROUP BY Type
Basing on your comment under Zohar Peled answer you probably looking for something like this:
; with cte as (select distinct ID from Table where Date < '$param')
select [data].*, [data2].[count]
from cte
cross apply
( select top 1 *
from Table
where Table.ID = cte.ID
and Table.Date < '$param'
order by Table.Date desc
) as [data]
cross apply
( select count(1) as [count]
from Table
where Table.ID = cte.ID
and Table.Date < '$param'
) as [data2]

SQL Server : select data between date range where there is missing data

Using SQL Server 2012, I have a script that inserts 4 rows of data into a table each day. The data looks like this:
Sometimes one or more of the rows is not inserted as the source data is incomplete. This looks like this - the second column is called commodityID:
There are times where more than one row could be missing.
I am trying to write a query that will show me what data is missing, so for the example above it would be for commodityID = 2. I have another table which is a calendar (lists all dates) table which I use with the query below to see if no data exists for a given date for all commodities.
SELECT *
FROM [Calendar]
WHERE (NOT EXISTS (SELECT ID, CommodityID, Price, DateEntered
FROM Spectron_DailyPricing
WHERE (CONVERT(date, DateEntered) = Calendar.date)))
AND (date BETWEEN '2015-05-14' AND dateadd(day, -1,GETDATE()))
ORDER BY date asc
I want to be able to run a SQL query that will look through all of the data and show the date and the commodityID that is missing. So for the example above it would show the following.
As my data spans a few years and there is the odd missing row there would be numerous results.
WITH
CTE_Numbers AS (
SELECT * FROM (VALUES (1),(2),(3),(4)) AS a(CommodityID)),
CTE_Calendar AS (
SELECT *
FROM [Calendar] c
CROSS JOIN CTE_Numbers n
WHERE c.date BETWEEN '2015-05-14' AND dateadd(day, -1,GETDATE()))
SELECT *
FROM CTE_Calendar c
LEFT JOIN Spectron_DailyPricing s
ON c.CommodityID = s.CommodityID
AND c.date = CONVERT(date, s.DateEntered)
WHERE
s.CommodityID IS NULL
ORDER BY c.date asc

SQL Query to update parent record with child record values

I need to create a Trigger that fires when a child record (Codes) is added, updated or deleted. The Trigger stuffs a string of comma separated Code values from all child records (Codes) into a single field in the parent record (Projects) of the added, updated or deleted child record.
I am stuck on writing a correct query to retrieve the Code values from just those child records that are the children of a single parent record.
-- Create the test tables
CREATE TABLE projects (
ProjectId varchar(16) PRIMARY KEY,
ProjectName varchar(100),
Codestring nvarchar(100)
)
GO
CREATE TABLE prcodes (
CodeId varchar(16) PRIMARY KEY,
Code varchar (4),
ProjectId varchar(16)
)
GO
-- Add sample data to tables: Two projects records, one with 3 child records, the other with 2.
INSERT INTO projects
(ProjectId, ProjectName)
SELECT '101','Smith' UNION ALL
SELECT '102','Jones'
GO
INSERT INTO prcodes
(CodeId, Code, ProjectId)
SELECT 'A1','Blue', '101' UNION ALL
SELECT 'A2','Pink', '101' UNION ALL
SELECT 'A3','Gray', '101' UNION ALL
SELECT 'A4','Blue', '102' UNION ALL
SELECT 'A5','Gray', '102'
GO
I am stuck on how to create a correct Update query.
Can you help fix this query?
-- Partially working, but stuffs all values, not just values from chile (prcodes) records of parent (projects)
UPDATE proj
SET
proj.Codestring = (SELECT STUFF((SELECT ',' + prc.Code
FROM projects proj INNER JOIN prcodes prc ON proj.ProjectId = prc.ProjectId
ORDER BY 1 ASC FOR XML PATH('')),1, 1, ''))
The result I get for the Codestring field in Projects is:
ProjectId ProjectName Codestring
101 Smith Blue,Blue,Gray,Gray,Pink
...
But the result I need for the Codestring field in Projects is:
ProjectId ProjectName Codestring
101 Smith Blue,Pink,Gray
...
Here is my start on the Trigger. The Update query, above, will be added to this Trigger. Can you help me complete the Trigger creation query?
CREATE TRIGGER Update_Codestring ON prcodes
AFTER INSERT, UPDATE, DELETE
AS
WITH CTE AS (
select ProjectId from inserted
union
select ProjectId from deleted
)
The following trigger will perform as you want.
CREATE TRIGGER Update_Codestring ON prcodes
AFTER INSERT, UPDATE, DELETE
AS
UPDATE projects
SET Codestring = (SELECT STUFF((SELECT ',' + prc.Code
FROM projects proj INNER JOIN prcodes prc ON proj.ProjectId = prc.ProjectId
WHERE proj.ProjectId = projects.ProjectId
ORDER BY 1 ASC FOR XML PATH('')),1, 1, ''))
where ProjectId in (SELECT ProjectId FROM inserted
UNION
SELECT ProjectId FROM deleted)
What you were missing in your original update statement was:
WHERE proj.ProjectId = projects.ProjectId - This will filter the subquery to only the project that is being updated. projects with no alias comes from the update statement so as update is applied against each row in projects only the current project row being updated.
WHERE ProjectId IN (SELECT ProjectId FROM inserted UNION SELECT ProjectId FROM deleted) - This will filter the update to affect only the rows with changed children.
Also you can simplify the update statement since it doesn't need the projects table included twice:
CREATE TRIGGER Update_Codestring ON prcodes
AFTER INSERT, UPDATE, DELETE
AS
UPDATE projects
SET Codestring = (SELECT STUFF((SELECT ',' + prc.Code
FROM prcodes prc
WHERE prc.ProjectId = projects.ProjectId
ORDER BY 1 ASC FOR XML PATH('')),1, 1, ''))
WHERE ProjectId IN (SELECT ProjectId FROM inserted
UNION
SELECT ProjectId FROM deleted)
Finally do you really need to store the Codestring on your Projects table? It's something that can easily be recalculated in a query at anytime or even put into a view. That was you don't have to worry about having to store the extra data and have a trigger to maintain it.

Resources