Get Max and Min of 2 Columns SQL Server 2008 R2 - sql

This query is the final part of a store procedure that manages to show me the results in this way:
;with final_comparativo as (
select s.CeEmplazamiento, avg(s.Totales) TotalGeneral , s2.TotGral, #Mes as Mes
from tmpSemanas s
cross join ( select avg(Totales) TotGral from tmpSemanas s2 where Totales >0) s2
group by s.CeEmplazamiento , s2.TotGral
union all
select ss.CeEmplazamiento, avg(ss.Totales) TotalGeneral , ss2.TotGral, #Mes_comparar as Mes
from tmpSemanas_comparar ss
cross join ( select avg(Totales) TotGral from tmpSemanas_comparar ss2 where Totales >0) ss2
group by ss.CeEmplazamiento , ss2.TotGral
)
--insert #tmpDatos
, maximo_minimo as (
select CeEmplazamiento,
max(case when Mes = #Mes then TotalGeneral else 0 end) as Mes_actual,
max(case when Mes = #Mes_comparar then TotalGeneral else 0 end) as Mes_comparar
from final_comparativo
where TotalGeneral <> 0
group by CeEmplazamiento
)
select * from maximo_minimo
drop table #tmpDatos
This is the current result table
CeEmplazamiento Month_current Month_compare
Celaya 76.500000 75.600000
Coecillo 79.000000 79.800000
Irapuato 77.500000 75.400000
León Sur 85.750000 87.600000
Oriente León 86.250000 85.200000
The store procedure asks you for 2 arguments corresponding to month_current (month of origin) month_compare (against which month you want to compare the month_current) so it is already a final calculation. But my problem lies in the following, I want this table to take the maximum and minimum of the current month and likewise for the column "Month_compare", I hope I have explained. More briefly, I would like it to remain this way.
CeEmplazamiento Month_current Month_compare
Leon Sur 85.75 87.60
Celaya 76.50 null
Irapuato null 75.40
As far as you can tell, it is not the same amount for all CeEsmplazamiento, those that are not in the current Month, are not shown but are taken into account for a graphic that is being done. I hope you can help me

Smth like this:
declare #t table(CeEmplazamiento varchar(100), Month_current money, Month_compare money);
insert into #t values
('Celaya', 76.500000, 75.600000),
('Coecillo', 79.000000, 79.800000),
('Irapuato', 77.500000, 75.400000),
('León Sur', 85.750000, 87.600000),
('Oriente León', 86.250000, 85.200000);
with cte1 as
(
select top 1 CeEmplazamiento, Month_current, null as Month_compare
from #t
order by Month_current asc
)
,cte2 as
(
select top 1 CeEmplazamiento, Month_current, null as Month_compare
from #t
order by Month_current desc
)
,cte3 as
(
select top 1 CeEmplazamiento, null as Month_current, Month_compare
from #t
order by Month_compare asc
)
,cte4 as
(
select top 1 CeEmplazamiento, null as Month_current, Month_compare
from #t
order by Month_compare desc
)
select *
from cte1
union all
select *
from cte2
union all
select *
from cte3
union all
select *
from cte4

Related

SQL query to find all rows with same timestamp + or - one second

Row 3 in the following table is a duplicate. I know this because there is another row (row 5) that was created by the same user less than one second earlier.
row record created_by created_dt
1 5734 '00E759CF' '2020-06-05 19:59:36.610'
2 9856 '1E095CBA' '2020-06-05 19:57:31.207'
3 4592 '1E095CBA' '2020-06-05 19:54:41.930'
4 7454 '00E759CF' '2020-06-05 19:54:41.840'
5 4126 '1E095CBA' '2020-06-05 19:54:41.757'
I want a query that returns all rows created by the same user less than one second apart.
Like so:
row record created_by created_dt
1 4592 '1E095CBA' '2020-06-05 19:54:41.930'
2 4126 '1E095CBA' '2020-06-05 19:54:41.757'
This is what I have so far:
SELECT DISTINCT a1.*
FROM table AS a1
LEFT JOIN table AS a2
ON a1.created_by = a2.created_by
AND a1.created_dt > a2.created_dt
AND a1.created_dt <= DATEADD(second, 1, a2.created_dt)
WHERE a1.created_dt IS NOT NULL
AND a.created_dt IS NOT NULL
This is what finally did the trick:
SELECT
a.*
FROM table a
WHERE EXISTS (SELECT TOP 1
*
FROM table a1
WHERE a1.created_by = a.created_by
AND ABS(DATEDIFF(SECOND, a.created_dt, a1.created_dt)) < 1
AND a.created_dt <> a1.created_dt)
ORDER BY created_dt DESC
You could use exists:
select t.*
from mytable t
where exists(
select 1
from mytable t1
where
t1.created_by = t.created_by
and abs(datediff(second, t.created_dt, t1.created_dt)) < 1
)
How about something like this
SELECT DISTINCT a1.*
FROM #a1 AS a1
LEFT JOIN #a1 AS a2 ON a1.[Created_By] = a2.[Created_By]
AND a1.[Record] <> a2.[Record]
WHERE ABS(DATEDIFF(SECOND, a1.[Created_Dt], a2.[Created_Dt])) < 1
Here is the sample query I used to verify the results.
DECLARE #a1 TABLE (
[Record] INT,
[Created_By] NVARCHAR(10),
[Created_Dt] DATETIME
)
INSERT INTO #a1 VALUES
(5734, '00E759CF', '2020-06-05 19:59:36.610'),
(9856, '1E095CBA', '2020-06-05 19:57:31.207'),
(4592, '1E095CBA', '2020-06-05 19:54:41.930'),
(7454, '00E759CF', '2020-06-05 19:54:41.840'),
(4126, '1E095CBA', '2020-06-05 19:54:41.757')
SELECT DISTINCT a1.*
FROM #a1 AS a1
LEFT JOIN #a1 AS a2 ON a1.[Created_By] = a2.[Created_By]
AND a1.[Record] <> a2.[Record]
WHERE ABS(DATEDIFF(SECOND, a1.[Created_Dt], a2.[Created_Dt])) < 1
I would suggest lead() and lag() instead of self-joins:
select t.*
from (select t.*,
lag(created_dt) over (partition by created_dt) as prev_cd,
lead(created_dt) over (partition by created_dt) as next_cd
from t
) t
where created_dt < dateadd(second, 1, prev_created_dt) or
created_dt > dateadd(second, -1, next_created_dt)

sql count new id that did not exists before for each month

I have the follow set of data
enter image description here
how can I write the sql to gives the result on right side?
that is the counting of unique id that did appeared previously for each month.
After long time of reading and reading his question, Ssiu wanted to ask the following:
So here is the test data in MS SQL: at that time he didn't clarify on postgresql
create table tmp1 (
ddate datetime
, iid int
)
insert into tmp1 values
('2017-11-01',1)
,('2017-11-02',2)
,('2017-11-03',3)
,('2017-11-04',4)
,('2017-11-05',5)
,('2017-11-06',5)
,('2017-11-07',5)
,('2017-12-01',1)
,('2017-12-02',2)
,('2017-12-03',3)
,('2017-12-04',6)
,('2017-12-05',7)
,('2018-01-01',1)
,('2018-01-02',2)
,('2018-01-03',3)
,('2018-01-04',4)
,('2018-01-05',8)
Disclaimer: The following is not the best approach for this problem. It is not applicable for more months, however it can give Ssiu a clue.
with cte(mmonth, iid) as (
select distinct convert(varchar(7), ddate, 120) mmonth
, iid
from tmp1
)
, cte_201711 as (
select * from cte where mmonth = '2017-11'
)
, cte_201712 as (
select * from cte where mmonth = '2017-12'
)
, cte_201801 as (
select * from cte where mmonth = '2018-01'
)
, cte_cnt201712 as(
select cte_201711.mmonth as mm201711
, cte_201711.iid as id201711
, cte_201712.mmonth as mm201712
, cte_201712.iid as id201712
from cte_201711
full outer join cte_201712
on cte_201712.iid = cte_201711.iid
)
, cte_cnt201801 as (
select cte_201711.mmonth as mm201711
, cte_201711.iid as id201711
, cte_201712.mmonth as mm201712
, cte_201712.iid as id201712
, cte_201801.mmonth as mm201801
, cte_201801.iid as id201801
from cte_201711
full outer join cte_201712
on cte_201712.iid = cte_201711.iid
full outer join cte_201801
on cte_201801.iid = cte_201712.iid
or cte_201801.iid = cte_201711.iid
)
--select * from cte_cnt201801 order by isnull(mm201711,'z'), isnull(mm201712,'z')
select '2017-12' mmonth, count(*) Ssiu
from cte_cnt201712
where mm201711 is null
union all
select '2018-01' mmonth, count(*) Ssiu
from cte_cnt201801
where mm201711 is null
and mm201712 is null
Note the data for the cte_cnt201801 CTE:
select * from cte_cnt201801 order by isnull(mm201711,'z'), isnull(mm201712,'z')
So the result for the above query is:

How to get recursivelevel using SQL Server 2012 hierarchyid?

I know its quite challenging, Is there any sql specialist please kindly help me to solve this.
I Have hierarchyID like below in NameHID column. Its representing /NameID/dadID/MomID/ respectively. Which means the students fatherid and the motherID. My Table Name is students.
this is my sample NAMEHID column
/2/8/5/
/5/11/12/
/8/7/9/
I need a output like
NameID | RecursiveLevel
2 0
5 1
7 2
8 1
9 2
11 2
12 2
From this Pic you can see the what is the RecursiveLevel. This tree representing something like ancestors of a specific node.
I need to show only the NameID and the Recursive level as out put.
if there Any other additional information need to do this?
Your data is not correct hierachyid.
You could do your job by using a split function and recursive cte
DECLARE #SampleData TABLE
(
NAMEHID varchar(30)
)
INSERT INTO #SampleData
(
NAMEHID
)
VALUES
('/2/8/5/'),('/5/11/12/'),('/8/7/9/')
;with temp AS
(
SELECT * FROM #SampleData sd
CROSS APPLY
(
SELECT * FROM [dbo].[SplitString](STUFF(LEFT(sd.NameHID,LEN(sd.NameHID) - 1),1,1,''),'/')
) cr
)
,cte AS
(
SELECT t.NameHID, t.[Value] , 0 AS Lvl FROM temp t
WHERE t.Pos = 1
AND NOT EXISTS (
SELECT * FROM temp t2
WHERE t2.[Value] = t.[Value] AND t2.Pos > 1
) -- root ID
UNION ALL
SELECT t2.NameHID, t2.[Value], cte.Lvl + 1
FROM cte
INNER JOIN temp t ON cte.[Value] = t.[Value] AND t.Pos = 1
INNER JOIN temp t2 ON t.NameHID = t2.NameHID AND t2.Pos > 1
)
SELECT cte.[Value] AS NameId, cte.Lvl
FROM cte
ORDER BY cte.Lvl, cte.[Value]
OPTION(MAXRECURSION 0)
Split function
CREATE FUNCTION [dbo].[SplitString] (#Text varchar(max),#Delimiter varchar(10))
Returns Table
As
Return (
Select Pos = Row_Number() over (Order By (Select null))
,Value = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
From (Select x = Cast('<x>'+ Replace(#Text,#Delimiter,'</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
);
Demo link: http://rextester.com/KPX84657

Sql Partitioning

I have Sql Table data and i need to filter only the Consecutive dates blocks as i highlighted on image below..
.
and i need to add custom rates for each row on that selected blocks(this rate can display with separate column on out put).If there is more than 6 rows captured then $200 apply for each column of that block.if it is less than 6 ,it will be $125.The out put should be like this
And it should group by EmpID.
i need to get the out put using MSSQL. Can any one help me
this is what i have done through the sql view
ALTER view [dbo].[vw_Test2] AS
SELECT
tbl2.ID as Tbl2ID,
tbl1.[EmpID],
tbl1.[ExpInDateTime] as Tbl1ExpDate,
tbl2.[ExpInDateTime] as Tbl2ExpDate,
case when(CONVERT(date,tbl1.[ActInDateTime]) = CONVERT(date, DATEADD(DAY,1,tbl2.[ExpInDateTime]))) then
1
else 0
end as Token
from [dbo].[vw_Test] tbl1 join [dbo].[vw_Test] tbl2
on tbl1.ID=(tbl2.ID+1)
GO
only thing is i have to do this using SQL views
Please try this as a view:
ALTER VIEW [dbo].[vw_Test2] AS
WITH PreResult AS (
SELECT p.Id,p.EmpID,p.[DateTime],CASE WHEN LEAD(p.diff)OVER(ORDER BY p.Id) > 1 OR LEAD(p.EmpID)OVER(ORDER BY p.Id)<>p.EmpID THEN 1 ELSE 0 END StartNewGroup
FROM (
SELECT t.Id,t.EmpID,t.[DateTime], COALESCE(DATEDIFF(day,LAG(t.[DateTime])OVER(PARTITION BY t.EmpID ORDER BY t.Id),t.[DateTime]),1) [diff]
FROM [dbo].[vw_Test] t
) p
)
SELECT r.Id,r.EmpID,r.[DateTime]
,CASE WHEN COUNT(*)OVER(PARTITION BY r.NewGroup ORDER BY r.NewGroup) >= 6 THEN 250 ELSE 125 END [Rate]
FROM (
SELECT b.Id,b.EmpID,b.[DateTime],1+COALESCE((SELECT SUM(a.StartNewGroup) FROM PreResult a WHERE a.Id<b.Id),0) NewGroup
FROM PreResult b
) r
GO
There is also query to play with:
CREATE TABLE #Test (Id BIGINT IDENTITY(1,1),EmpID BIGINT, [DateTime] DATETIME)
INSERT INTO #Test (EmpID,[DateTime]) VALUES (5,'20150106'),(5,'20150107'),(5,'20150109'),
(5,'20150110'),(5,'20150126'),(5,'20150127'),
(5,'20150128'),(5,'20150129'),(5,'20150130'),
(5,'20150131'),(10,'20121203'),(10,'20121204'),
(10,'20121205'),(10,'20121206'),
(10,'20121207'),(10,'20121208'),(10,'20121209')
;WITH PreResult AS (
SELECT p.Id,p.EmpID,p.[DateTime],CASE WHEN LEAD(p.diff)OVER(ORDER BY p.Id) > 1 OR LEAD(p.EmpID)OVER(ORDER BY p.Id)<>p.EmpID THEN 1 ELSE 0 END StartNewGroup
FROM (
SELECT t.Id,t.EmpID,t.[DateTime], COALESCE(DATEDIFF(day,LAG(t.[DateTime])OVER(PARTITION BY t.EmpID ORDER BY t.Id),t.[DateTime]),1) [diff]
FROM #Test t
) p
)
SELECT r.Id,r.EmpID,r.[DateTime]
,CASE WHEN COUNT(*)OVER(PARTITION BY r.NewGroup ORDER BY r.NewGroup) >= 6 THEN 250 ELSE 125 END [Rate]
FROM (
SELECT b.Id,b.EmpID,b.[DateTime],1+COALESCE((SELECT SUM(a.StartNewGroup) FROM PreResult a WHERE a.Id<b.Id),0) NewGroup
FROM PreResult b
) r
DROP TABLE #Test
Please let me know if you have any questions.

SQL to Mimic Excel

I have an finance issue that we are trying to put into a SQLServer 2005 database (default installation). We are doing quarterly comparison from this year to the same quarter last year i.e. (2013Q1 - 2012Q1) / 20132Q1. Can someone write a query to return an ordered list from 1 - 9 with the quarter over quarter as described above?
In data set
QUART REV
2011Q1 6,175,352
2011Q2 6,591,067
2011Q3 6,219,978
2011Q4 6,189,939
2012Q1 7,178,652
2012Q2 6,731,467
2012Q3 6,949,978
2012Q4 6,679,939
2013Q1 6,242,802
2013Q2 6,421,902
2013Q3 6,667,007
2013Q4 6,575,004
Expected output
QUART COMP
1 0.1625
2 0.0213
3 0.1174
4 0.0792
5 -0.1304
6 -0.0460
7 -0.0407
8 -0.0157
Thanks in advance ;-)
I agree with the above comment, it is much easier if you split quart:
create table t
( yr int not null
, qt int not null
, salary int not null
, primary key (yr,qt) )
insert into t (yr,qt,salary)
values (2011,1,6175352)
, (2011,2,6591067)
, (2011,3,6219978)
, (2011,4,6189939)
, (2012,1,7178652)
, (2012,2,6731467)
, (2012,3,6949978)
, (2012,4,6679939)
, (2013,1,6242802)
, (2013,2,6421902)
, (2013,3,6667007)
, (2013,4,6575004)
select row_number() over (order by yr, qt) as quart, comp
from (
select t1.yr, t1.qt
, (1.0*t1.salary - (select salary
from t t2
where t2.yr = t1.yr - 1
and t2.qt = t1.qt)
) / t1.salary comp
from t t1
where t1.yr >= 2012
)
my numbers deviates from yours, I have not investigate why but it should give you a start.
Lot of formatting in a SQL query, but the exercise was fun. Normally, you should elevate formatting (such as rounding) to the application level, but since you're trying to emulate Excel...
/*sample data*/
DECLARE #T TABLE ( Quart CHAR(6), Rev INT )
INSERT INTO #T
( Quart, Rev )
VALUES ( '2011Q1', 6175352 ),
( '2011Q2', 6591067 ),
( '2011Q3', 6219978 ),
( '2011Q4', 6189939 ),
( '2012Q1', 7178652 ),
( '2012Q2', 6731467 ),
( '2012Q3', 6949978 ),
( '2012Q4', 6679939 ),
( '2013Q1', 6242802 ),
( '2013Q2', 6421902 ),
( '2013Q3', 6667007 ),
( '2013Q4', 6575004 );
/*query begins here
cte is used to parse quart column into years & quarters */
WITH cte
AS ( SELECT Yr = CONVERT(SMALLINT, LEFT(Quart, 4))
, Qt = RIGHT(Quart, 1)
, Rev
FROM #T
)
/*join cte to itself to compare last year same quarter
ROW_NUMBER used to get sequential ordering
CONVERT to numeric and rounding to get formatting
*/
SELECT QUART = ROW_NUMBER() OVER (ORDER BY b.Yr
, b.Qt) ,
COMP = CONVERT(NUMERIC(5,4), ROUND((a.Rev-b.Rev*1.0)/ b.Rev, 4))
FROM cte a
JOIN cte b ON b.Qt = a.Qt
AND b.Yr = a.Yr - 1