In SQL I need to send four prompts: one of the prompt values will be 'none'. If it is none, I want it to return all results. Basically none is saying there is no where clause. But how?
Select ID_PK
From STG_TBL_DIM
WHERE GL_FK in (Select Value from dbo.split(#Prompt,','))
If I'm understanding correctly that 'none' will be in you #Prompt variable this should work.
WHERE (
GL_FK in (Select Value from dbo.split(#Prompt,','))
or
'none' in (Select Value from dbo.split(#Prompt,','))
)
Instead of doing the split twice I would put these values into a #temp table and then subqueries.
Select
Value
into #Values
from dbo.split(#Prompt,',')
...
the rest of your query
...
WHERE (
GL_FK in (Select Value from #Values)
or
'none' in (Select Value from #Values)
)
where charindex('none',#Prompt) > 0
or GL_FK in (Select Value from dbo.split(#Prompt,','))
i think this solves it.
Of course, there is the issue of maybe none being an substring of other words, ie. nonewrecords... so it really depends about details, ie, what format Promt has for 1 value and more then 1 value,
if its a , separated list then doing this
where charindex(',none,',','+#Prompt+',') > 0
or GL_FK in (Select Value from dbo.split(#Prompt,','))
is a simple solution
Related
I have a table PROCESS . Currently it doesnt not have any records in it. I need to return one hardcoded row if the table doesnt have any record .
I am doing a select when the primary key column "id" is null then i hard code the values and return it as below
SELECT CASE WHEN p.ID IS NULL THEN 1 ELSE p.ID END ,
CASE WHEN p.COMPANY IS NULL THEN 'COMP1' ELSE p.COMPANY END
FROM PROCESS p
I took reference from the below link
If-else statement in DB2/400
But it always returns me an empty row in DB2 database and not the hardcoded values used in select statement.
08:50:27 SUCCESS SELECT 0.307 0.301 0 Empty result set fetched
08:50:29 FINISHED 0.307 0.301 0 Success: 1 Failed: 0
Please help me on this
no way to do in this way, since a primary key could never be null. and select * from empty table return no row (0 row) it do not return null.
you can do it like that:
select ID, COMPANY from PROCESS
UNION ALL
select 1 as ID, 'COMP1' as COMPANY from sysibm.sysdummy1 where (select count(*) from PROCESS) = 0;
There are various ways you could achieve what (I think) you want. This is one
SELECT
COALESCE(ID,1) AS ID
, COALESCE(COMPANY,'COMP1') AS COMPANY
FROM
TABLE(VALUES 1) AS DUMMY(D)
LEFT JOIN
PROCESS
ON
1=1
I have been banging my head trying to come up with the correct logic (SQL Server 2012) needed to achieve something I would imagine would be fairly routine but I have been unable to find any examples of this anywhere. Basically, I have 3 columns in a table: product, flag, value. It is possible for a product to be listed multiple times within the table but only once with a unique flag (i.e. product1 can have flag1 or flag2 with different/identical but there will never be 2 records with product1 and flag1 and different/identical values).
The flag represents a pre-defined value (1,2,3,4) and the intention behind this field is to be able to assign a unique mathematical equation based on the value of the flag. The end result would yield a single product, the unique flag, and a new cumulative total based on the mathematical equation output. For instance, let's say product1 was listed 4 times with flag values of flag1, flag2, flag3, flag4 (see below):
Product-----Flag-----Value
Product1----Flag1----1.00
Product1----Flag2----3.00
Product1----Flag3----5.00
Product1----Flag4----7.00
Product-----Flag-----Value
Product1----Flag1----1.00 (flag1 value)
Product1----Flag2----4.00 (flag1+flag2 value)
Product1----Flag3----6.00 (flag1+flag3 value)
Product1----Flag4----10.00 (flag2+flag4 value)
Flag1 is defined as add flag1 only. Flag2 is defined as add flag1 and flag2. Flag 3 is defined as add flag1 and flag 3. Flag 4 is defined as add flag2 and flag4. the new output would be product1 listed four times with flag values of flag1, flag2, flag3, flag4 but new values as flag1, flag1_flag2, flag1+flag3, flag2+flag4.
I have tried to apply the logic via a case statement but I can't figure out how to traverse all the products for each condition and I have tried to go with a running totals solution but I am not sure how to incorporate the flag condition into it so it only performs a running total for when those conditions are true. Any assistance and/or article to help get me going down the right path would be greatly appreciated.
While I'm not sure I fully understand your question I think this might be what you want. For this to work it assumes flag1 is always present when flags 1 through 3 are and that flag2 is present when flag4 is.
;with cte as (
select
product,
max(case when flag = 'Flag1' then Value end) as f1Value,
max(case when flag = 'Flag2' then Value end) as f2Value,
max(case when flag = 'Flag3' then Value end) as f3Value,
max(case when flag = 'Flag4' then Value end) as f4Value
from flags group by Product
)
select
flags.Product,
flags.Flag,
flags.Value as "Org. value",
case flag
when 'Flag1' then f1Value
when 'Flag2' then f1Value + f2Value
when 'Flag3' then f1Value + f3Value
when 'Flag4' then f2Value + f4Value
else flags.Value -- take the present value when flag is not Flag1-4
end as "New value"
from flags
inner join cte on flags.Product = cte.Product
Take a look at this Sample SQL Fiddle to see it in action.
You can join a table to itself, and pick the conditions appropriately:
SELECT p1.product,p1.Flag,p1.Value + COALESCE(p2.Value,0)
FROM
Products p1
left join
Products p2
on
p1.Product = p2.Product and
p2.Flag = CASE p1.Flag
--1 doesn't need a previous value
WHEN 2 THEN 1
WHEN 3 THEN 1
WHEN 4 THEN 2
END
I assumed and tried on Range values.
CREATE TABLE #tmp (Product VARCHAR(10), flag VARCHAR(10),value numeric(13,2))
GO
INSERT INTO #tmp
SELECT 'Product1' , 'Flag1',1
UNION
SELECT 'Product1' , 'Flag2',3
UNION
SELECT 'Product1' , 'Flag3',5
UNION
SELECT 'Product1' , 'Flag4',7
GO
;WITH cte
AS
(
SELECT row_number () OVER(
ORDER BY flag) 'row',*
FROM #tmp
)
SELECT *,value 'RT'
FROM cte
WHERE row = 1
UNION
SELECT * ,(
SELECT cte.value
FROM cte
WHERE row = 1
) + value 'RT'
FROM cte
WHERE row BETWEEN 2
AND 3
UNION
SELECT * ,(
SELECT cte.value
FROM cte
WHERE row =2
) + value 'RT'
FROM cte
WHERE row >3
GO
DROP TABLE #tmp
(Please note, I require a SQL Server 2005 solution)
I have a UNION query, where the first part returns multiple rows in a particular order, and the second part returns a single row which MUST the last row of the result set.
The easiest way I've found so far is to include an extra "sort" column, BUT I do not want this column to be returned with the data set.
Please note, this example has a single column, but the real query has many columns, built via dynamic query...
SELECT [TITLE],
(SELECT COUNT(*) FROM dbo.[OTHERTABLE] WHERE ...) AS [VALUE],
0 AS [EXTRAORDER]
FROM dbo.[LOOKUPTABLE]
UNION
SELECT 'Total',
(SELECT COUNT(*) FROM dbo.[OTHERTABLE]),
1 AS [EXTRAORDER]
ORDER BY [EXTRAORDER], [TITLE]
How can I creating this so that all the columns excluding EXTRAORDER are returned (preferably without manually listing all the desired columns)?
Unless anybody can come up with a better solution, I have currently settled for the following...
(I was heading down the same route as SQLhint.com was in their answer. Unfortunately their answer - at the time of writing - is still incorrect, and therefore I cannot upvote it. The Total row will still be ordered within the results of the main SELECT, rather than be "appended" to the end.)
Ideally I wanted a solution that didn't require the replication of all the columns required in the final data set. Unfortunately this solution does NOT satisfy this requirement, but at least it works!
The solution was to use CTE...
; WITH [DATA] AS (
SELECT [TITLE],
(SELECT COUNT(*) FROM dbo.[OTHERTABLE] WHERE ...) AS [VALUE],
0 AS [EXTRAORDER]
FROM dbo.[LOOKUPTABLE]
UNION
SELECT 'Total',
(SELECT COUNT(*) FROM dbo.[OTHERTABLE]),
1
)
SELECT [TITLE], [VALUE]
FROM [DATA]
ORDER BY [EXTRAORDER], [TITLE]
I think the best way is to return 2 result sets, but to respond strictly to your question:
SELECT [title], [value]
FROM
(SELECT [TITLE],
(SELECT COUNT(*) FROM dbo.[OTHERTABLE] WHERE ...) AS [VALUE],
0 AS [EXTRAORDER]
FROM dbo.[LOOKUPTABLE]
UNION
SELECT 'Total',
(SELECT COUNT(*) FROM dbo.[OTHERTABLE]),
1 AS [EXTRAORDER]) as A
ORDER BY CASE WHEN [title] = 'Total' THEN 'zzz' ELSE [title] END
How about this?
SELECT [TITLE], [VALUE]
FROM (
SELECT [TITLE],
(SELECT COUNT(*) FROM dbo.[OTHERTABLE] WHERE ...) AS [VALUE]
FROM dbo.[LOOKUPTABLE]
UNION
SELECT 'Total',
(SELECT COUNT(*) FROM dbo.[OTHERTABLE])
) [DATA]
ORDER BY (case when [TITLE] = 'Total' then 1 else 0 end), [TITLE]
This removed the [EXTRAORDER] column but still orders based on the [TITLE] treating 'Total' as the last item.
I am wondering if there is some easy way, a function, or other method to return data from a query with the following results.
I have a SQL Express DB 2008 R2, a table that contains numerical data in a given column, say col T.
I am given a value X in code and would like to return up to three records. The record where col T equals my value X, and the record before and after, and nothing else. The sort is done on col T. The record before may be beginning of file and therefore not exist, likewise, if X equals the last record then the record after would be non existent, end of file/table.
The value of X may not exist in the table.
This I think is similar to get a range of results in numerical order.
Any help or direction in solving this would be greatly appreciated.
Thanks again,
It might not be the most optimal solution, but:
SELECT T
FROM theTable
WHERE T = X
UNION ALL
SELECT *
FROM
(
SELECT TOP 1 T
FROM theTable
WHERE T > X
ORDER BY T
) blah
UNION ALL
SELECT *
FROM
(
SELECT TOP 1 T
FROM theTable
WHERE T < X
ORDER BY T DESC
) blah2
DECLARE #x int = 100
;WITH t as
(
select ROW_NUMBER() OVER (ORDER BY T ASC) AS row_nm,*
from YourTable
)
, t1 as
(
select *
from t
WHERE T = #x
)
select *
from t
CROSS APPLY t1
WHERE t.row_nm BETWEEN t1.row_nm -1 and t1.row_nm + 1
I have a SQL Server Reporting Service form that is supposed to query and display metrics across a number of years.
The form can optionally receive years it is supposed to display as a parameter. The problem I have is specifying "if #year is not set then include everything, otherwise limit to the specified years."
The query I have currently is:
SELECT name, collected_year, value, [order]
FROM rpt_competency_metric
WHERE ( len( #year ) = 0 OR collected_year IN ( #year ) )
AND competency_id = #competency_id
Which works when #year is blank, but fails with the error The len function requires 1 argument. when passing in multiple values.
I've tried count( #year ) and DataLength( #year ) without success.
OK, I know this is stale, but I think I have an answer now.
You can set another parameter to the count of your multi-valued parameter and pass that into the query. So you will end up with this on the SQL Side:
SELECT name, collected_year, value, [order]
FROM rpt_competency_metric
WHERE ( #mvpCount = 0 OR collected_year IN ( #year ) )
AND competency_id = #competency_id
On the RS side you would use an expression to set #mvpCount to the count of your #year:
=Parameters!Year.Count
I haven't tried it, but I think it would work.
Thanks, Queso.
The solution you suggested below works as a charm. I was fighting with it for over half a day.
SELECT
name
, collected_year
, value
, [order]
FROM rpt_competency_metric
WHERE ( len('#year') = 0
OR collected_year IN ( #year ) )
AND competency_id = #competency_id
I found no satisfactory answer to this on the web so after much thought and prayer I came up with this solution.
The trouble that I and everybody else is having is that the only way to handle an SSRS multi-value variable is by adding in the where clause:
Table.FieldName in (#MultiValue)
So to check to see if there is something in the #MultiValue variable you will need to do the following. In the query field or in a stored procedure you will need to find out if there were any selections made and stuff them into an in memory sql table. Then in another query get the row count and stuff that into a variable. Then use that variable in the query to determine if you should search on that criteria.
Here is an example in SQL:
DECLARE #GroupCnt int;
Declare #TblGroup Table (GroupID int);
Insert INTO #TblGroup (GroupID)
SELECT ItemID
FROM Groups
WHERE ItemId in (#Group)
SELECT #GroupCnt = COUNT(*)
From #TblGroup
SELECT CAST(ItemId AS Varchar(10)) AS ProviderID, ProviderShortName AS Location
FROM Provider as prov
WHERE (IsActive = 1)
and (#GroupCnt = 0 or prov.GroupId in (#Group))
UNION ALL
SELECT '' AS ProviderID, '(NONE)' AS Location
ORDER BY Location
The "and (#GroupCnt = 0 or prov.GroupId in (#Group))" code is where the magic happens but in order to do this you must get the #GroupCnt variable from the first two queries.
FYI, I add the UNION ALL so that the user will have the option to not select any options.
Multi-Value Parameters are converted into a comma-separated list. So you are ending up with this when you use the len function:
SELECT name, collected_year, value, [order]
FROM rpt_competency_metric
WHERE ( len(2007,2008) = 0 OR collected_year IN ( 2007,2008 ) )
AND competency_id = #competency_id
Which explains your error as well. One of these might work, but I haven't tested them:
SELECT name, collected_year, value, [order]
FROM rpt_competency_metric
WHERE ( #year is null OR collected_year IN ( #year ) )
AND competency_id = #competency_id
Or:
SELECT name, collected_year, value, [order]
FROM rpt_competency_metric
WHERE ( rtrim(ltrim(convert(varchar,'#year'))) = '' OR collected_year IN ( #year ) )
AND competency_id = #competency_id
Try the above with and without the single quotes around #year.
Don't know what SSRS does with a multi-value parameter in a literal string, but if it replaces it outright this might work, which is close to what you have:
SELECT name, collected_year, value, [order]
FROM rpt_competency_metric
WHERE ( len('#year') = 0 OR collected_year IN ( #year ) )
AND competency_id = #competency_id