Cannot filter And Or for multiple rows - sql-server-2008-r2

Currently, I have a table (2 columns ColumnName, Value) with data like this:
ColumnName Value
CustomerName Facebook
CompanyName Google
How can I write a query with And / Or condition to satisfy the request:
With And:
CustomerName = 'YAHOO' And CompanyName = 'Google' will return 0 records
With Or:
CustomerName = 'Facebook' Or CompanyName = 'Google' will return 2 records
I have no idea to begin.
Please advise.
Thanks.

You can research EAV data model for reasons why this model may not scale well.
You can query like so:
declare #YourTable table (ColumnName varchar(100), Value varchar(100) primary key (ColumnName, Value));
insert into #YourTable
select 'CustomerName', 'Facebook' union all
select 'CompanyName', 'Google';
--with And...
select *
from #YourTable
where (ColumnName = 'CustomerName' and Value = 'Yahoo') and
(ColumnName = 'CompanyName' and Value = 'Google')
--with Or...
select *
from #YourTable
where (ColumnName = 'CustomerName' and Value = 'Facebook') or
(ColumnName = 'CompanyName' and Value = 'Google')

Related

Postgresl : Loop a list of values to create SELECT with mulitple WHERE clause

I have a simple SQL query such as
SELECT * from tableName
WHERE (field = 'value1') OR (field = 'value2') OR (field = 'value3') ...
I am lazy enough to write hardcode write the SQL query like above.
I want to extract value1, value2 , ... in an array ( or any collections)
How to write the query above so that it can loop the list of values ?
# declare array
# loop for each element in the array
SELECT * from tableName WHERE (field = element)
# or even better
# build the WHERE clause with a loop
whereClause = (field = 'value1') OR (field = 'value2') OR (field = 'value3') ...
SELECT * from tableName WHERE whereClause
As a_horse_with_no_name has mentioned you can
Check if the field is in an array
SELECT *
FROM tableName
WHERE field = ANY(ARRAY['value1', 'value2'])
and you can use a language of your choice to fill these values dynamically
or if those values are already in a table you can
SELECT *
FROM tableName
WHERE field IN (SELECT field FROM otherTableName)

Using CASE outside SELECT in table-valued function

I'm trying to select the same columns from a different table/view depending on the value of an argument (#ruleset). As it is not possible to pass the name of the table as a parameter nor to construct the name inside the function, used CASE structure outside the select statements. However, I get an error:
"Only one expression can be specified in the select list when the subquery is not introduced with EXISTS."
[Hope I get this right, it is my first question here.]
CREATE FUNCTION app.fgProduct
(
#ruleset nvarchar(50),
#matno nvarchar(50),
#datarevision int
)
RETURNS TABLE
AS
RETURN
(
SELECT
CASE WHEN #ruleset = 'G1' THEN
(
SELECT
#matno AS ProductId
,#datarevision AS DataRevision
,[ProductName]
FROM [ruleset].[g1gxProduct]
WHERE ProductId = #matno
)
WHEN #ruleset = 'G2' THEN
(
SELECT
#matno AS ProductId
,#datarevision AS DataRevision
,[ProductName]
FROM [ruleset].[g2gxProduct]
WHERE ProductId = #matno
)
END
)
There's a bunch of other views, so this whole issue cannot be solved in one procedure. Above is an example of a function which is used to generate new records based on various rule sets (= sets of views).
CASE is an expression and not for conditional flow. Use IF/ELSE instead.
The error is related to the select statements that are returning more than one column in the sub query. You can only return one column in the statements:
SELECT
#matno AS ProductId
,#datarevision AS DataRevision
,[ProductName]
The solution is to declare a result table and insert into it, just like #EzLo suggested in the comment.
CREATE FUNCTION app.fgProduct
(
#ruleset nvarchar(50),
#matno nvarchar(50),
#datarevision int
)
RETURNS #ret TABLE (
[ProductID] [nvarchar](50) NOT NULL,
[DataRevision] [int] NOT NULL,
[ProductName] [nvarchar](50) NULL
)
AS
BEGIN
IF #ruleset = 'G1'
INSERT INTO #ret
SELECT
#matno AS ProductId
,#datarevision AS DataRevision
,[ProductName]
FROM [ruleset].[g1gxProduct]
WHERE ProductId = #matno
ELSE
IF #ruleset = 'G2'
INSERT INTO #ret
SELECT
#matno AS ProductId
,#datarevision AS DataRevision
,[ProductName]
FROM [ruleset].[g2gxProduct]
WHERE ProductId = #matno
RETURN
END

I cannot manage to insert multiple rows when having multiple fields to get data from

I ran into a problem with regards to trying to insert multiple rows in a table at once. I know it sounds easy, but here is the twist. The procedure itself gets data from a trigger, and the trigger returns a number of rows. So i need to make 1 insert statement to insert those rows and some other data. here is the code:
CREATE PROCEDURE [a01].[usp_raiseFriendAlerts]
(#AccountA UNIQUEIDENTIFIER, #AccountB UNIQUEIDENTIFIER)
AS
BEGIN
DECLARE #typeID TINYINT;
DECLARE #notificationID UNIQUEIDENTIFIER = NEWID();
DECLARE #accountAName NVARCHAR(356);
DECLARE #accountBName NVARCHAR(356);
SET #typeID = ( SELECT typeID
FROM [a01].[tbl_notificationTypes]
WHERE typeName = 'Added friend');
SET #accountAName = ( SELECT accountUsername
FROM [a01].[tbl_userAccounts]
WHERE accountID = #AccountA);
SET #accountBName = ( SELECT accountUsername
FROM [a01].[tbl_userAccounts]
WHERE accountID = #AccountB);
DECLARE #AccountIDZZ UNIQUEIDENTIFIER;
SET #AccountIDZZ = (SELECT friendAccountID
FROM [a01].[udf_getAddedFriendContacts](#AccountA, #AccountB)
EXCEPT
SELECT targetAccountID
FROM [a01].[tbl_blockedAccounts]);
INSERT INTO [a01].[tbl_notificationsInbox] (notificationID, notificationMessage, notificationDate, accountID, typeId)
VALUES (#notificationID, #accountAName + ' is now friends with ' + #accountBName, SYSDATETIMEOFFSET(), #AccountIDZZ , #typeID)
END;
GO
Try this:
CREATE PROCEDURE [a01].[usp_raiseFriendAlerts]
(
#AccountA UNIQUEIDENTIFIER
, #AccountB UNIQUEIDENTIFIER
)
AS
BEGIN
DECLARE #typeID TINYINT
, #notificationID UNIQUEIDENTIFIER = NEWID()
, #accountAName NVARCHAR(356)
, #accountBName NVARCHAR(356)
, #AccountIDZZ UNIQUEIDENTIFIER;
SELECT #typeID = typeID
FROM [a01].[tbl_notificationTypes]
WHERE typeName = 'Added friend';
SELECT #accountAName = accountUsername
FROM [a01].[tbl_userAccounts]
WHERE accountID = #AccountA;
SELECT #accountBName = accountUsername
FROM [a01].[tbl_userAccounts]
WHERE accountID = #AccountB;
INSERT INTO [a01].[tbl_notificationsInbox]
(
notificationID
, notificationMessage
, notificationDate
, accountID
, typeId
)
SELECT #notificationID
, #accountAName + ' is now friends with ' + #accountBName
, SYSDATETIMEOFFSET()
, AIDZZ.accountID
, #typeID
FROM (
SELECT friendAccountID AS 'accountID'
FROM [a01].[udf_getAddedFriendContacts](#AccountA, #AccountB)
EXCEPT
SELECT targetAccountID AS 'accountID'
FROM [a01].[tbl_blockedAccounts]
) AS AIDZZ
END;
GO

Return a value if select returned null

I need to return a value if select returned null. however I found a solution here by putting a query in a sub-query
SELECT COALESCE((SELECT id FROM tbl WHERE id = 9823474), 4) AS id FROM RDB$DATABASE;
The query above would return Null because the value 9823474 does not exist in the table but I want to return a value in that case (for ex 4) so I found the only solution to use select inside sub query and then COALESCE would work, If I did not do that COALESCE will also return Null.
Is it the only solution ?
No, that is not an only way for example
Select first 1 id from (
Select id FROM tbl WHERE id = 9823474
Union All
Select 4 from rdb$database)
Or you can use anonymous procedure http://firebirdsql.su/doku.php?id=execute_block
EXECUTE BLOCK RETURNS ( id integer )
AS
BEGIN
IF ( EXISTS (SELECT * FROM tbl WHERE id = 9823474) )
THEN id = 9823474;
ELSE id = 4;
SUSPEND;
END
... there always are many methods there

How to filter records for all rows?

I am designing a SQL query to extract all records from a given table. But the trick here is that this logic is based on a numeric database field. So there are 4 choices: 0,1,2,3. If user selects 0,1, or 2, then my query returns rows with the specified value. But if they choose 3, it should return all of the rows. How do I do this in SQL? I know if this was a string, I could do something like:
WHERE = CASE WHEN = 3 THEN '%' ELSE END
But in this case, is an integer. Sounds relatively simple but I'm getting errors.
Try this:
SELECT *
FROM <YOUR_TABLE>
WHERE
(
<YOUR_COLUMN> = #InputValue OR
3 = #InputValue
)
Where #InputValue is the name of parameter sent to the query.
The simplest way is to do this:
select MyColumn
from MyTable
where ( MyValue = #MyParameter or #MyParameter = 3)
If your interested in better optimization, then you can do this, but it is less maintainable:
if (#MyParameter = 3)
select MyColumn
from MyTable
else
select MyColumn
from MyTable
where MyValue = #MyParameter
If I were forced to implement this functionality, then I would probably do this, just to make things clear:
declare #AllRecords nchar(1)
if (#MyParameter = 3)
set #AllRecords = N'Y'
else
set #AllRecords = N'N'
select MyColumn
from MyTable
where (MyValue = #MyParameter or #AllRecords = N'Y')
Hopefully, I won't ever have to implement a system that mixes flags and data value in this way.
UPDATED
Here is a version that should work with your expanded requirements (this requires one of the newer versions of SQL Server, I think):
declare #SelectedLevels table (LevelId int not null primary key)
if #LevelId = 3
insert into #SelectedLevels (LevelId) values (1), (2)
else if #LevelId = 5
insert into #SelectedLevels (LevelId) values (0), (1), (2)
else
insert into #SelectedLevels (LevelId) values (#LevelId)
select mt.MyColumn
from MyTable mt
inner join #SelectedLevels sl on sl.LevelId = MyTable.LevelId
if #Param = 3
begin
select *
from #T
end
else
if #Param = 2
begin
select *
from #T
where id in (0,1)
end
else
begin
select *
from #T
where id = #Param
end