SQL Server - fill NULL row values with certain logic - sql-server

I've got a PIVOT table output in SQL Server Management Studio. Every row contains data that are either filled or NULL. I need to fill the NULL values according to the following logic:
If value is NULL, then go further to the left (in the row) and fill it with the closest value to the left.
If there are no values to the left, then use the closest value to the right to fill it.
Thanks for your kind help,
Dave

Since you have a limited number of columns, coalesce() should do the trick
Select Product
,Time1 = coalesce(Time1,Time2,Time3,Time4,Time5,Time10,Time15,Time20,Time30)
,Time2 = coalesce(Time2,Time3,Time4,Time5,Time10,Time15,Time20,Time30,Time1)
,Time3 = coalesce(Time3,Time4,Time5,Time10,Time15,Time20,Time30,Time1,Time2)
,Time4 = coalesce(Time4,Time5,Time10,Time15,Time20,Time30,Time1,Time2,Time3)
,Time5 = coalesce(Time5,Time10,Time15,Time20,Time30,Time1,Time2,Time3,Time4)
,Time10 = coalesce(Time10,Time15,Time20,Time30,Time1,Time2,Time3,Time4,Time5)
,Time15 = coalesce(Time15,Time20,Time30,Time1,Time2,Time3,Time4,Time5,Time10)
,Time20 = coalesce(Time20,Time30,Time1,Time2,Time3,Time4,Time5,Time10,Time15)
,Time30 = coalesce(Time30,Time1,Time2,Time3,Time4,Time5,Time10,Time15,Time20)
From ...
Pivot ...

Related

How to query values when a column has N value

So I have the following table:
And I'm trying to write a Query where I can send the code BR_BN as a variable in my WHERE clause
and if I get BR_BN then I want to retrieve the records with this code AND the records with the Code_FS RB02. On the other side when I get the value AB_CP, I want to include the recordes with the Code_FS RB01.
Here's the Query I've tried so far:
DECLARE #Code_OB VARCHAR(20) = 'BR_BN'
SELECT * FROM Dummy_AV
WHERE FK = 2
OR
(#Code_OB = 'BR_BN' AND Code_FS = 'RB02' AND Code_FS = #Code_OB)
But it doesn't work, it retrieves all the records regardless of the FK, and/or the #Code_FS.
How can I achieve this?
Thanks for the help.
You don't note the FK = 2 being needed, yet you have it in front of an OR in the WHERE clause. I think this is what you're after, if it isn't exactly what you're aiming for hopefully it gets you on the right track. For future questions, always helpful to paste your sample data as data instead of an image.
DECLARE #Code_OB VARCHAR(20) = 'BR_BN'
SELECT * FROM Dummy_AV
WHERE FK = 2 -- you will get all rows where this is true
OR
((#Code_OB = Code_OB AND Code_FS = 'RB02') OR (Code_OB = 'AB_CP' AND Code_FS = 'RB01')) -- you will get all rows where one of these is true

Power Pivot: DAX for Same Value Sequential Count

Please reference the following example table.
The actual table would be contained in PowerPivot.
There are multiple runs identified by sequential numbering.
Based on what we want to observe through filtering, each run has an associated value.
Here's simplified version of the current data:
Current Table
Common Columns for all Data:
Part: Uniquely defines the group. In this case, it's part or device.
Run: Identifies a same test count.
Value: The outcome generated from the test.
What I've been trying to add is an additional three columns:
Desired1: Same_Value_Count: This counts consecutive same values.
Desired2: Same_Max: Gives the maximum same value count.
Desired3: Same_Min: Give the minimum same value count.
This would result in the following PivotTable:
Resulting Table
I am having trouble formulating the proper DAX syntax to accomplish the two extra columns.
Keep in mind, I'd like to show the whole table as is.
I have a calculated column here called count_seq_dup:
=CALCULATE(COUNTROWS(table), ALLEXCEPT(table, table[3_Value]), EARLIER(Table[2_Run]) >= CSVsource[2_Run])
It worked perfectly for a single part, but does not work with multiple parts parts and when other filtering or slicers are applied.
I'm close, but it's not exactly what I'm looking for, and I can't figure out the syntax in DAX to get it right.
Can anyone help me?
For the Same_Value_Count, try something like this:
Same_Value_Count =
VAR part = 'table'[1_Part]
VAR val = 'table'[3_Value]
VAR run = 'table'[2_Run]
VAR tblpart = FILTER ( 'table', 'table'[1_Part] = part && 'table'[2_Run] <= run )
RETURN
run - CALCULATE ( MAX ( 'table'[2_Run] ), FILTER ( tblpart, [3_Value] <> val ) )
This will return the maximum same value count for a part / value combination.
Max Count =
VAR part = 'table'[1_Part]
VAR val = 'table'[3_Value]
RETURN
CALCULATE (
MAX ( 'table'[Same_Value_Count] ),
FILTER ( 'table', [3_Value] = val && 'table'[1_Part] = part )
)

Filter SQL datatable according to different parameters, without a WHERE clause

I'm building an application that needs to allow the user to filter a data table according to different filters. So, the user will have three different filter posibilites but he might use only one, or two or the three of them at the same tame.
So, let's say I have the following columns on the table:
ID (int) PK
Sede (int)
Programa (int)
Estado (int)
All of those columns will store numbers, integers. The "ID" column is the primary key, "Sede" stores 1 or 2, "Programa" is any number between 1 and 15, and "Estado" will store numbers between 1 and 13.
The user may filter the data stored in the table using any of those filters (Sede, Programa or Estado). But the might, as well, use two filters, or the three of them at the same time.
The idea is that this application works like the data filters on Excel. I created a simulated table on excel to show what I want to achieve:
This first image shows the whole table, without applying any filter.
Here, the user selected a filter for "Sede" and "Programa" but leaved the "Estado" filter empty. So the query returns the values that are equal to the filter, but leaves the "Estado" filter open, and brings all the records, filering only by "Sede" (1) and "Programa" (6).
In this image, the user only selected the "Estado" filter (5), so it brings all the records that match this criteria, it doesn't matter if "Sede" or "Programa" are empty.
If I use a SELECT clasuse with a WHERE on it, it will work, but only if the three filters have a value:
DECLARE #sede int
DECLARE #programa int
DECLARE #estado int
SET #sede = '1'
SET #programa = '5'
SET #estado = '12'
SELECT * FROM [dbo].[Inscripciones]
WHERE
([dbo].[Inscripciones].[Sede] = #sede)
AND
([dbo].[Inscripciones].[Programa] = #programa)
AND
([dbo].[Inscripciones].[Estado] = #estado)
I also tryed changing the "AND" for a "OR", but I can't get the desired result.
Any help will be highly appreciated!! Thanks!
common problem: try using coalesce on the variable and for the 2nd value use the field name you're comparing to. Be careful though; Ensure it's NULL and not empty string being passed!
What this does is take the first non-null value of the variable passed in or the value you're comparing to.. Thus if the value passed in is null the comparison will always return true.
WHERE
[dbo].[Inscripciones].[Sede] = coalesce(#sede, [dbo].[Inscripciones].[Sede])
AND
[dbo].[Inscripciones].[Programa] = coalesce(#programa, [dbo].[Inscripciones].[Programa])
AND
[dbo].[Inscripciones].[Estado] = coalesce(#estado, [dbo].[Inscripciones].[Estado])
If sede is null and programa and estado are populated the compare would look like...
?=? (or 1=1)
?=programa variable passed in
?=Estado variable passed in
Boa Sorte!
Thank you all for your anwers. After reading the article posted in the comments by #SeanLange I was finally able to achieve what was needed. Using a CASE clause in the WHERE statement solves the deal. Here's the code:
SELECT
*
FROM [dbo].[Inscripciones]
WHERE
([dbo].[Inscripciones].[Sede] = (CASE WHEN #sede = '' THEN [dbo].[Inscripciones].[Sede] ELSE #sede END))
AND
([dbo].[Inscripciones].[Programa] = (CASE WHEN #programa = '' THEN [dbo].[Inscripciones].[Programa] ELSE #programa END))
AND
([dbo].[Inscripciones].[Estado] = (CASE WHEN #estado = '' THEN [dbo].[Inscripciones].[Estado] ELSE #estado END))
AND
([dbo].[Inscripciones].[TipoIngreso] = (CASE WHEN #tipoingreso = '' THEN [dbo].[Inscripciones].[TipoIngreso] ELSE #tipoingreso END))
Thanks again!!

SQL Server 2008 Stored Proc Performance where Column = NULL

When I execute a certain stored procedure (which selects from a non-indexed view) with a non-null parameter, it's lightning fast at about 10ms. When I execute it with a NULL parameter (resulting in a FKColumn = NULL query) it's much slower at about 1200ms.
I've executed it with the actual execution plan and it appears the most costly portion of the query is a clustered index scan with the predicate IS NULL on the fk column in question - 59%! The index covering this column is (AFAIK) good.
So what can I do to improve the performance here? Change the fk column to NOT NULL and fill the nulls with a default value?
SELECT top 20 dbo.vwStreamItems.ItemId
,dbo.vwStreamItems.ItemType
,dbo.vwStreamItems.AuthorId
,dbo.vwStreamItems.AuthorPreviewImageURL
,dbo.vwStreamItems.AuthorThumbImageURL
,dbo.vwStreamItems.AuthorName
,dbo.vwStreamItems.AuthorLocation
,dbo.vwStreamItems.ItemText
,dbo.vwStreamItems.ItemLat
,dbo.vwStreamItems.ItemLng
,dbo.vwStreamItems.CommentCount
,dbo.vwStreamItems.PhotoCount
,dbo.vwStreamItems.VideoCount
,dbo.vwStreamItems.CreateDate
,dbo.vwStreamItems.Language
,dbo.vwStreamItems.ProfileIsFriendsOnly
,dbo.vwStreamItems.IsActive
,dbo.vwStreamItems.LocationIsFriendsOnly
,dbo.vwStreamItems.IsFriendsOnly
,dbo.vwStreamItems.IsDeleted
,dbo.vwStreamItems.StreamId
,dbo.vwStreamItems.StreamName
,dbo.vwStreamItems.StreamOwnerId
,dbo.vwStreamItems.StreamIsDeleted
,dbo.vwStreamItems.RecipientId
,dbo.vwStreamItems.RecipientName
,dbo.vwStreamItems.StreamIsPrivate
,dbo.GetUserIsFriend(#RequestingUserId, vwStreamItems.AuthorId) as IsFriend
,dbo.GetObjectIsBookmarked(#RequestingUserId, vwStreamItems.ItemId) as IsBookmarked
from dbo.vwStreamItems WITH (NOLOCK)
where 1 = 1
and vwStreamItems.IsActive = 1
and vwStreamItems.IsDeleted = 0
and vwStreamItems.StreamIsDeleted = 0
and (
StreamId is NULL
or
ItemType = 'Stream'
)
order by CreateDate desc
When it's not null, do you have
and vwStreamItems.StreamIsDeleted = 0
and (
StreamId = 'xxx'
or
ItemType = 'Stream'
)
or
and vwStreamItems.StreamIsDeleted = 0
and (
StreamId = 'xxx'
)
You have an OR clause there which is most likely the problem, not the IS NULL as such.
The plans will show why: the OR forces a SCAN but it's manageable with StreamId = 'xxx'. When you use IS NULL, you lose selectivity.
I'd suggest changing your index make StreamId the right-most column.
However, a view is simply a macro that expands so the underlying query on the base tables could be complex and not easy to optimise...
The biggest performance gain would be for you to try to loose GetUserIsFriend and GetObjectIsBookmarked functions and use JOIN to make the same functionality. Using functions or stored procedures inside a query is basically the same as using FOR loop - the items are called 1 by 1 to determine the value of a function. If you'd use joining tables instead, all of the items values would be determined together as a group in 1 pass.

How to Filter variables for SP, to return only one value from many in SQL View

In a SQL View, I have 5 boolean variables and one int variable.
out of 5 boolean variables only one variable will be true for a single data row,
Task Type boolVerySmall Datestart TagName
Architecture Setup -- Doc Code True 1900-01-01 00:00:00.000 Design_09
idProject boolsmall boolMedium boolLarge boolVeryLarge intHours
4 False False False False 0
The above data is for one row... in this row, when I download the data from database to excel sheet, I have to display only the value which is true (boolVerySmall ,boolsmall, boolMedium,boolLarge, boolVeryLarge, intHours) should be displayed in a single column,
I have written a Stored procedure for this. I am finding it difficult to get a particular row which has TRUE of intHours>0.
I am adding the sql query below. Please help me
SELECT dbo.tblResourceTaskList.txtTask, dbo.tblIndividualRelativeData.txtProductType, dbo.tblResourceTaskList.boolVerySmall,
dbo.tblResourceTaskList.dtActualCompletionDate, dbo.tblEffortCodes.txtTagName, dbo.tblResourceTaskList.txtTaskNotes, dbo.tblResourceTaskList.idSubProject, dbo.tblResourceTaskList.idLaunch, dbo.tblResourceTaskList.idResource, dbo.tblResourceTaskList.boolSmall, dbo.tblResourceTaskList.boolMedium, dbo.tblResourceTaskList.boolLarge, dbo.tblResourceTaskList.boolVeryLarge,
dbo.tblResourceTaskList.intDirectHours
FROM dbo.tblResourceTaskList INNER JOIN dbo.tblProjectUsers ON dbo.tblResourceTaskList.idSubProject = dbo.tblProjectUsers.idSubProject AND
dbo.tblResourceTaskList.idResource = dbo.tblProjectUsers.idUser INNER JOIN
dbo.tblLaunchInfo ON dbo.tblResourceTaskList.idLaunch = dbo.tblLaunchInfo.idLaunch INNER JOIN dbo.tblIndividualRelativeData ON dbo.tblResourceTaskList.idIndividualRelativeEffort = dbo.tblIndividualRelativeData.idIndividualRelativeEffort LEFT OUTER JOINdbo.tblEffortCodes ON dbo.tblResourceTaskList.idEffortCode = dbo.tblEffortCodes.idEffortCode
My stored procedure is
SELECT txtTask, txtProductType, boolVerySmall, txtTagName, txtTaskNotes,
dtActualCompletionDate
FROM tblResourceTaskList_View
WHERE (idSubProject = #idSubProjectIndex )
as the first row from db has TRUE for boolVerySmall, then SP should return this value and if its other than that it should give that value.
Instead of filling True in excel sheet, I , have to assign VS for boolVerySmall, S - Small, M - Medium, L - Large VL- VeryLarge in the excelsheet.
So please help me how to work on this.
1. Assigning shortnames (like VS... for the bool var's).
2. Returning only one value (boolverysmall or ... ) and assigning VS to that and fill it in excel.
3. if all the bools are false, then intHours should be assinged...
Kindly help me.
Thanks
Ramm
I am able to assign values to SP using CASE statements.
Now, its workign fine.
Thanks
Ramm

Resources