I am creating a database in SSMS and I am trying to calculate AVG from 2 columns from 2 tablets; I wrote :
;WITH combined AS
(
SELECT Datum_narodenia
FROM Zamestnanci
UNION ALL
SELECT Datum_narodenia
FROM ObčaniaSR
)
SELECT AVG(Datum_narodenia)
FROM combined;
But I got this error:
Msg 8117, Level 16, State 1Operand data type date is invalid for avg operator.
I created table 1 :
CREATE TABLE Zamestnanci
(
id_Zamestnanca int not null,
Meno varchar(50) null,
Priezvisko varchar(50)null,
Adresa varchar(50) null,
Datum_narodenia date null,
PRIMARY KEY (id_Zamestnanca)
);
CREATE TABLE ObčaniaSR
(
id_Občana int not null,
Meno varchar(50) null,
Priezvisko varchar(50) null,
Adresa varchar(50) null,
Datum_narodenia date null,
Zápis_v_trestnom_registry varchar(50) null,
PRIMARY KEY (id_Občana)
);
Datum_narodenia means Date_of_birth from witch I try to calculate AVG.
What is best way to calculate AVG age according to you? Thank you for your answers and advice.
Pretty close calculation of age (lots of nitty-gritty in this answer) uses the difference in hours between the date and now, divided by the number of hours in a year (8766/24 = 365.25), which tries to roughly account for leap years; it is imperfect, but a pretty good trade-off IMHO between simple and right:
SELECT DATEDIFF(HOUR,'19860201',GETDATE())/8766;
So:
;WITH combined AS
(
SELECT Datum_narodenia
FROM Zamestnanci
UNION ALL
SELECT Datum_narodenia
FROM ObčaniaSR
)
SELECT AVG(DATEDIFF(HOUR, Datum_narodenia, GETDATE())/8766)
FROM combined;
Now, this does integer math, so you might instead want:
;WITH combined AS
(
SELECT Datum_narodenia
FROM Zamestnanci
UNION ALL
SELECT Datum_narodenia
FROM ObčaniaSR
)
SELECT CONVERT(DECIMAL(5,1),
AVG(DATEDIFF(HOUR, Datum_narodenia, GETDATE())/8766.0))
FROM combined;
Related
I have the set of data below which I created to emulate what my live data looks like. I am trying to pull the LATEST standard costs based on date ascending from a standard cost CTE where the dates considered are only those which are before the inventory transaction date. What I have so far is this, which works but is not very efficient based on the execution plan.
CREATE TABLE stdcosts
(item varchar(20) not null,
indt date not null,
rev integer not null,
[MC00.010] money default 0,
[OC00.000] money default 0,
[GC00.025] money default 0,
[MS00.010] money default 0) ;
INSERT INTO stdcosts
VALUES
('201226-03','02/26/2019',1,2000,0,100,50),
('201226-03','09/07/2019',2,700,0,0,50),
('201226-03','10/07/2019',3,500,0,20,10)
CREATE TABLE inventoryOH
(item varchar(20) not null,
warehouse varchar(8) not null,
TransDate date not null,
seq integer not null default 1,
owner varchar(10) ,
project varchar(10),
orderID varchar(10),
onHand integer default 0,
Age bigint,
costMethod varchar(15) ,
WVG_flag varchar(1),
WVG char(4),
rowno int );
INSERT INTO inventoryOH
VALUES
('201226-03','B','6/18/2019',1,'','','NPO312979',5,134,'STANDARD','N','',1),
('201226-03','B','9/3/2019',1,'','','NPO315960',14,57,'STANDARD','N','',2),
('201226-03','B','9/23/2019',1,'','','SFC037624',1,37,'STANDARD','N','',3),
('201226-03','B','10/1/2019',1,'','','NPO316472',6,29,'STANDARD','N','',4);
Output:
SELECT i.*, s.*
FROM inventoryOH i
LEFT JOIN stdcosts s
ON s.item = i.item
AND s.indt <= i.TransDate
AND s.rev IN (SELECT MAX(s1.rev)
FROM stdcosts s1
WHERE s1.item = s.item
AND s1.indt <= i.TransDate)
I am wondering if anyone has a way to optimize this using either a rank/row number or additional method(s) to make this run faster.
link --> http://sqlfiddle.com/#!18/2b4865/2
You can use OUTER APPLY to perform the lateral join.
For each row in inventoryOH we need to find one row from stdcosts, that has the same item, that has indt on or before TransDate and that has the maximum rev.
SELECT
inventoryOH.*
,Costs.*
FROM
inventoryOH
OUTER APPLY
(
SELECT TOP(1)
item
,indt
,rev
,[MC00.010]
,[OC00.000]
,[GC00.025]
,[MS00.010]
FROM stdcosts
WHERE
stdcosts.item = inventoryOH.item
AND stdcosts.indt <= inventoryOH.TransDate
ORDER BY
stdcosts.rev DESC
) AS Costs
;
To make it work efficiently you should create an index in stdcosts table on (item, indt) include (rev, [MC00.010],[OC00.000],[GC00.025],[MS00.010]). The order of columns in an index is important.
I'm not sure what should be the logic around the rev values, but if you need the latest row based only on indt (not on rev), then sorting should be by indt: ORDER BY stdcosts.indt DESC. It would also work more efficiently with the suggested index.
If i have a table variable like that how to loop over this var to make some processing :
DECLARE #userData TABLE(
userId int NOT NULL,
dayDate datetime NOT NULL,
transIn datetime NULL,
transOut datetime NULL,
attIn datetime NULL,
attOut datetime NULL,
MissionIn datetime NOT NULL,
MissionOut datetime NOT NULL,
empState varchar(10) NULL
);
INSERT INTO #userData
SELECT userid, trans_date,transtime_in,transtime_out,att_start_time,att_end_time,#Mission_fromdatetime,#Mission_todatetime,day_flag
FROM datatable_o a
WHERE a.userid = #userid AND a.trans_date = #date ORDER BY transtime_in ;
According to the comments the Whole case :
If the work starts at : att_start_time and ends at att_end_time (work period]
Every employee could check -in and check-out many times in the same date so we could follow him .
the check-in stored in transtime_in
and check-out stored in transtime_out
and i have day_flag so i could know the day is 'W' work day or 'E' weekend
Now considering all these information in addition to the emp_num ,date
I want to calc for the an employee External mission over time :
I have four cases :
No check-in-out && Not work day [weekend] So the employee
should take all the mission period as overtime
No check-in-out && Work day [Absent] so the employee should
take only the mission period out of the work period
There are check-in-outs && Not work day [week end] so the
employee should take only the mission period out of these
check-ins-outs
There are check-ins-outs && work day so the employee should take
only the mission period out of these check-ins-outs and at the same
time out of work period .
Example :
emp_num date att_start att_end mission-in mission-out
672 2015-3-4 07:05:00 13:30:00 12:12:00 20:00:00
emp_num date trans_in trans_out
672 2015-3-4 06:54:00 11:10:00
672 2015-3-4 12:00:00 14:05:00
You can loop through your table by taking help from a copy of that table:
with regard to your question assuming your table is:
DECLARE #userData TABLE(
userId int NOT NULL,
/*Other fields*/
);
and the data of your table is:
INSERT INTO #userData
/*A SELECT or values*/
now create a copy of your table as:
DECLARE #userData_2 TABLE(
userId int NOT NULL,
/*Structure should be the same as #userData*/
);
INSERT INTO #userData_2
SELECT * FROM #userData
now you can do the loop and do whatever you want:
DECLARE #userId INT
WHILE EXISTS (SELECT * FROM #userData_2)
BEGIN
SET #userId=(SELECT TOP 1 userId FROM #userData)
/*
DO YOUR TRANSACTION HERE
*/
DELETE FROM #userData_2 WHERE userId=#userID
END
NOTICE: this assumes the userId is unique, if not then you need to have a unique field, or use a composite fields instead of userId.
Given the following tables:
CREATE TABLE [Contact]
(
[Id] INTEGER NOT NULL,
[Uri] CHARACTER VARYING(255) NOT NULL,
[CreatedOn] DATETIMEOFFSET NOT NULL
);
CREATE TABLE [Availability]
(
[Id] TINYINT NOT NULL,
[Name] CHARACTER VARYING(255) NOT NULL,
[CreatedOn] DATETIMEOFFSET NOT NULL
);
CREATE TABLE [ContactAvailability]
(
[Id] BIGINT NOT NULL,
[ContactId] INTEGER NOT NULL,
[AvailabilityId] INTEGER NOT NULL,
[CreatedOn] DATETIMEOFFSET NOT NULL
);
I am attempting to get a list of all of the contacts and the durations for which they have been in any of the availabilities for the current day.
The ContactAvailability table ends up having records such as:
(1, 1, 1, '01/01/2014 08:00:23.51 -07:00'),
(2, 1, 3, '01/01/2014 08:15:38.01 -07:00'),
(3, 1, 3, '01/01/2014 08:15:38.02 -07:00'),
(4, 2, 2, '01/01/2014 08:18:33.12 -07:00')
These records represent a Contact's transition from one Availability to another, and also from one Availability to the same. It is essentially a running status that is logged on an interval.
The query I have come up with only queries for a particular user and only gets a list of their availabilities for the current day, but it won't calculate how long the Contact has been in any Availability. I am not sure where to start when it comes to that.
This is that query:
SELECT [Contact].[Uri] AS [ContactUri],
[Availability].[Name] AS [AvailabilityName],
[ContactAvailability].[CreatedOn]
FROM [ContactAvailability]
INNER JOIN [Contact] ON [Contact].[Id] = [ContactAvailability].[ContactId]
INNER JOIN [Availability] ON [Availability].[Id] = [ContactAvailability].[AvailabilityId]
WHERE [Contact].[Uri] = 'sip:contact#example.com' AND
[ContactAvailability].[CreatedOn] >= '06/30/2014 00:00:00 -07:00' AND
[ContactAvailability].[CreatedOn] < '07/01/2014 00:00:00 -07:00'
You can use a Window Function in combination with a CTE.
I think this should work, not tested yet :) So you might have to change your column names.
with SourceTable
( ContactID, AvailabilityID, NewDate, OldDate)
as(
SELECT ContactAvailability.ContactID AS ContactID,
ContactAvailability.AvailabilityID AS AvailabilityID,
[ContactAvailability].[CreatedOn] As NewDate,
LAG(ContactAvailability.CreatedON) OVER (Partition By ContactAvailability.ContactID order by ContactAvailability.CreatedOn) as OldDate
FROM [ContactAvailability])
SELECT [Contact].[Uri] AS [ContactUri],
[Availability].[Name] AS [AvailabilityName],
SourceTable.OldDate as PreviousAvailabilityDate,
SourceTable.NewDate as CurrentAvailibilityDate,
SourceTable.NewDate - SourceTable.OldDate as DifferenceBetweenAvailability,
[ContactAvailability].[CreatedOn]
FROM SourceTable
INNER JOIN [Contact] ON [Contact].[Id] = SourceTable.[ContactId]
INNER JOIN [Availability] ON [Availability].[Id] = SourceTable.[AvailabilityId]
If you need to calculate the total time somebody has been in a certain availability (f.e. personA is in availability A then B then A again and then C) you will have to add another cte and partition on ContactAvailability.AvailabilityID and then make a sum of your calculated field.
I want to make a custom paging according to the following link:
but my stored procedure is in informix:
so I search for the equivalent row_number() I find this solution
but when I use it in my procedure I get the following error:
SQL error -944 Cann't use "first","limit","skip" in this context !
How to rewrite the stored procedure in the previous link with informix rules?
my procedure has multiple unions is like this:
create procedure get_inbox_page(p_emp_num smallint, p_task_code smallint, p_main_code smallint default 0, p_year smallint default 0,p_page int)
returning varchar(60) as v_page_view, varchar(60) as v_task_name, smallint as v_task_code, varchar(60) as v_sp_name, varchar(60) as v_db_name, varchar(60) as v_column_key, smallint as v_trans_serial,
DATETIME YEAR TO FRACTION(3) as v_trans_date, varchar(60) as v_trans_desc , varchar(60) as v_emp_name, varchar(60) as v_values_key, smallint as v_old_state_serial,
smallint as v_new_state_serial, smallint as v_main_code, smallint as v_year, varchar(60) as v_page_new, smallint as v_task_type, smallint as v_task_status,smallint as v_mail_maincode,smallint as v_mail_year,smallint as v_mail_number,smallint as v_trans_year , smallint as candidate_flag ;
Select ......
UNION
Select ......
UNION
Select ......
You cannot use FIRST, SKIP etc, because each SELECT statement within the UNION collection is self-contained.
Perhaps you could try creating a VIEW that encapsulates the SELECT ... UNION ... SELECT logic, and then apply the FIRST/SKIP logic to that.
try this
;
WITH tempPagedRecord
AS ( SELECT Column1 ,
Column2 ,
Column3
FROM TableName AS e--Your query with union
UNION ALL
SELECT Column1 ,
Column2 ,
Column3
FROM TableName AS e--Your query with union
)
SELECT * ,
ROW_NUMBER() OVER ( ORDER BY Column1 ASC ) AS RowNumber--RowNumber over some column
FROM tempPagedRecord
WHERE RowNumber BETWEEN(#PageIndex -1) * #PageSize + 1 AND(((#PageIndex -1) * #PageSize + 1) + #PageSize) - 1
I need a select query ..
Environment : SQL DBA -SQL SERVER 2005 or newer
Example :
In this sample table, if I select top 20 no duplicate records should come and next record should be in 20 records .
Example :
123456 should not repeat in 20 records and if 18th is duplicate, in place of 18th, 19th record should come and in 19th—20th should come, in 20th ---21st should come .
No concern of Asc or Desc for rows .
Lookup Table before
Id Name
123456 hello
123456 hello
123654 hi
123655 yes
LookUp Table after
Id Name
123456 hello
123654 hi
123655 yes
My table:
CREATE TABLE [dbo].[test](
[Id] [int] IDENTITY(1,1) NOT NULL,
[ContestId] [int] NOT NULL,
[PrizeId] [int] NOT NULL,
[ContestParticipantId] [int] NOT NULL,
[SubsidiaryAnswer] [varchar](256) NOT NULL,
[SubsidiaryDifference] [bigint] NOT NULL,
[AttemptTime] [datetime] NOT NULL,
[ParticipantName] [varchar](250) NOT NULL,
[IsSubscribed] [bit] NOT NULL,
[IsNewlyRegistered] [bit] NOT NULL,
[IsWinner] [bit] NOT NULL,
[IsWinnerConfirmed] [bit] NOT NULL,
[IsWinnerExcluded] [bit] NOT NULL) ON [PRIMARY]
My question is: from this select, we actually need the first 20, but unique ones.
SELECT TOP 20 * FROM test order by SubsidiaryDifference
When we do the above query, we have currently some double in there. In case there is a double, we need take them only 1 time and take the next one
Any one know this issue ?
Thanks in advance :)
Reading your question, it appears you don't really want to delete the rows from the table - you just want to display the TOP 20 distinct rows - you try something like this:
;WITH LastPerContestParticipantId AS
(
SELECT
ContestParticipantId,
-- add whatever other columns you want to select here
ROW_NUMBER() OVER(PARTITION BY ContestParticipantId
ORDER BY SubsidiaryDifference) AS 'RowNum'
FROM dbo.Test
)
SELECT TOP (20)
ContestParticipantId,
-- add whatever other columns you want to select here
SubsidiaryDifference
FROM
LastPerContestParticipantId
WHERE
RowNum = 1
This will show you the most recent row for each distinct ContestParticipantId, order by SubsidiaryDifference - try it!
Update #2: I've created a quick sample - it uses the data from your original post - plus an additional SubID column so that I can order rows of the same ID by something...
When I run this with my CTE query, I do get only one entry for each ID - so what exactly is "not working" for you?
DECLARE #test TABLE (ID INT, EntryName VARCHAR(50), SubID INT)
INSERT INTO #test
VALUES(123456, 'hello', 1), (123456, 'hello', 2), (123654, 'hi', 1), (123655, 'yes', 3)
;WITH LastPerId AS
(
SELECT
ID, EntryName,
ROW_NUMBER() OVER(PARTITION BY ID ORDER BY SubID DESC) AS 'RowNum'
FROM #test
)
SELECT TOP (3)
ID, EntryName
FROM
LastPerId
WHERE
RowNum = 1
Gives an output of:
ID EntryName
123456 hello
123654 hi
123655 yes
No duplicates.