Comparing dates in iif() in SQL Server - sql-server-2008

I am trying to use the following query in SQL Server
SELECT [AL].[Subscriptions].Id,
[AL].[Subscriptions].name,
[AL].[Subscriptions].description,
[AL].[Subscriptions].price,
[AL].[Subscriptions].iconFileName,
IIf(a.expiryDate > Now(), 'TRUE', 'FALSE') AS isSubsByUser
FROM [AL].[Subscriptions]
LEFT JOIN (SELECT *
FROM [AL].[UserSubscriptions]
WHERE userId = 13259) AS a
ON Subscriptions.Id = a.itemid;
but always get the error
Error in list of function arguments: '>' not recognized.
Unable to parse query text.
How do I resolve it?

Like Martin Smith said you need to use a case statement. Also it looks like you are only using a couple of fields in the derived table therefor I would suggest not using *. I put a example below.
SELECT [AL].[Subscriptions].Id,
[AL].[Subscriptions].name,
[AL].[Subscriptions].description,
[AL].[Subscriptions].price,
[AL].[Subscriptions].iconFileName,
case when a.expiryDate > GetDate() then 'TRUE' else 'FALSE' end AS isSubsByUser
FROM [AL].[Subscriptions]
LEFT JOIN (SELECT expiryDate, itemid
FROM [AL].[UserSubscriptions]
WHERE userId = 13259) AS a
ON Subscriptions.Id = a.itemid;

Related

SqlAlchemy puts SELECT Subquery in FROM clause instead of SELECT

My target SQL is the following, which is valid,
SELECT a.agreement_group_id,
(select id from agreement_t where agreement_group_id = a.agreement_group_id and
active = 'Y'),
...
FROM ets.agreement_t a
WHERE requester_uniqueidentifier = '0010079170'
GROUP BY a.agreement_group_id
ORDER BY a.agreement_group_id
But SqlAlchemy is producing the following -- and complaining that I don't have anon_1 in GROUP BY due to its placement of the sub-select in FROM,
SELECT agreement_t_1.agreement_group_id AS agreement_t_1_agreement_group_id,
anon_1.id AS anon_1_id,
...
FROM ets.agreement_t AS agreement_t_1,
(SELECT ets.agreement_t.id AS id
FROM ets.agreement_t, ets.agreement_t AS agreement_t_1
WHERE ets.agreement_t.agreement_group_id = agreement_t_1.agreement_group_id AND
ets.agreement_t.active = 'Y') AS anon_1
WHERE agreement_t_1.requester_uniqueidentifier = '0010079170'
GROUP BY agreement_t_1.agreement_group_id, anon_1.id
ORDER BY agreement_t_1.agreement_group_id
Python SqlAlchemy code:
agreement = aliased(AgreementT)
subqueryActive = db_session.query(AgreementT.id).filter(
(AgreementT.agreement_group_id == agreement.agreement_group_id),
(AgreementT.active == 'Y')
).subquery()
result = (db_session.query(
agreement.agreement_group_id,
subqueryActive,
...
.filter(*filters)
.group_by(agreement.agreement_group_id)
.order_by(agreement.agreement_group_id)
.all())
I don't need any other Joins. As you can see, the subquery subqueryActive already references the alias agreement which is used in the main query. So why is the Sub-Select not placed properly in the SELECT, but rather in the FROM, with the following error?
psycopg2.errors.GroupingError: column "anon_1.id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: ...ent_group_id AS agreement_t_1_agreement_group_id, anon_1.id ...
^
If the sub-Select should be part of the SELECT, we can't use .subquery(), we need to use .label() instead.
Example here: https://stackoverflow.com/a/43655840/1005607
Thanks for the tip #Ilja Everilä

While loop for selecting field names?

I have a nasty, nasty data layout that I am forced to work with. I finally got a working query using C# and a for loop executing the same query over and over but adjusting which fields are called, but now I am wondering if it is possible to do it with a while loop. I am getting an error, and I am not sure if it is because I am using Faircom / C-tree as the database, or if there is something wrong with my query. I am normally a Mysql user.
the table has 20 fields I care about and want to extract into a csv list. They are codetype1-codetype20 and I want it to be something like value1, value2, value3... where as it is now I get them all back one at a time. Trouble is that codetype1 is dependent on another field to determine where I go look for the info on that code, which is why the case statements.
DROP PROCEDURE IF EXISTS proc_loop_test;
CREATE PROCEDURE proc_loop_test()
SET #index = 1;
WHILE(#index < 21) DO
SELECT Replace(Concat(To_char(apptid), To_char(.#index) ), ' ', '') AS reference_id,
apptid AS a_reference_id,
CASE
WHEN c.ee > 0 THEN d.amt
ELSE insfee.amt
END AS amount,
CASE
WHEN c.ee > 0 THEN Rtrim(e.moneyname)
ELSE insname.namefeecatid
END AS moneyschedule_name,
CASE codetype#index
WHEN 1 THEN rtrim(a.descript)
ELSE rtrim(b.descript0)
END AS description,
CASE codetype#index
WHEN 1 THEN rtrim(a.abbrevdescript)
ELSE rtrim(b.abbrev0)
END AS abbreviated_description,
CASE codetype#index
WHEN 1 THEN rtrim(a.thiscode)
ELSE rtrim(b.thiscode0)
END AS code
FROM meetings
LEFT JOIN
(
SELECT admin.table2.procid,
admin.table2.this_code_id,
admin.v_table1.descript,
admin.v_table1.abbrevdescript,
admin.v_table1.thiscode
FROM admin.table2
INNER JOIN admin.v_table1
ON admin.table2.this_code_id = admin.v_table1.this_code_id) AS a
ON meetings.codeid#index = a.procid
LEFT JOIN
(
SELECT admin.v_table1.descript AS descript0,
admin.v_table1.abbrevdescript AS abbrev0,
admin.v_table1.thiscode AS thiscode0,
admin.v_table1.this_code_id
FROM admin.v_table1) AS b
ON meetings.codeid#index = b.this_code_id
LEFT JOIN
(
SELECT patid AS id,
ee
FROM admin.customer) AS c
ON meetings.patid = c.id
LEFT JOIN
(
SELECT this_code_id AS redid,
eecategoryid,
amt
FROM admin.eeule) AS d
ON c.ee = d.eecategoryid
AND d.redid = b.this_code_id
LEFT JOIN
(
SELECT eecategoryid AS namefeecatid,
moneyname
FROM admin.eeulenames) AS e
ON d.eecategoryid = e.namefeecatid
LEFT JOIN (SELECT pi.customer_id,
pi.primarykk_id AS picid,
pi.primarykk_name,
pi.first_name,
pi.last_name,
i.groupname,
i.ee
FROM admin.v_pir AS pi
LEFT JOIN admin.money AS i
ON pi.primarykk_id = i.insid) AS
ins
ON ins.customer_id = c.id
LEFT JOIN (SELECT this_code_id AS redid,
eecategoryid,
amt
FROM admin.eeule) AS insfee
ON ins.ee = insfee.eecategoryid
AND insfee.redid = b.this_code_id
LEFT JOIN (SELECT eecategoryid AS namefeecatid,
moneyname
FROM admin.eeulenames) AS insname
ON insfee.eecategoryid = insname.namefeecatid
WHERE codeid#index >= 1
END WHILE;
END;
I have never used a while loop, and while I understand somewhat I am supposed to select this to go INTO something, do I need to create a temp table, or can it all just be stored in memory till the end of the loop and returned.
For what it is worth, the entire SELECT query works in C# when you replace the #index with concatenating format " . index . "
Based on the information that you have provided, it is strongly suggested that you reach out to your vendor for this. You're attempting to create a stored procedure, however, using a mySQL proprietary syntax. Stored procedure support is unique to each database vendor. FairCom's c-treeACE SQL actually uses Java for cross platform support and .NET for Windows.
https://docs.faircom.com/doc/jspt/#cover.htm
Stored procedure development requires a strong knowledge of the database layout which is highly application dependent. In this case, many legacy application dependencies may be involved. Again, your best source of information will be your application vendor.

SQL Field Update Syntax Issues with complex selection logic

The query below works fine and is what I need.
I want to add a new keyword onto "Keywords" e.g.
UPDATE bugs SET bug.keywords = CONCAT(bug.keywords, ', Report:DevProcess')
However no matter where I place this in the logic below, I get a syntax error.
The web examples I have seen and in Stackoverflow are for simple
Update ... WHERE .... examples.
SET #StartDate = '2016-03-01';
SET #EndDate = '2016-03-31';
SELECT
bugs_activity.bug_id,
bug.status_whiteboard AS Whiteboard,
bug.keywords AS Keywords,
bug.bug_status,
bug.resolution,
SUM(CASE WHEN fd.name = 'bug_status' AND (bugs_activity.added = 'VERIFIED' OR bugs_activity.added = 'CLOSED') THEN 1 ELSE 0 END) AS ClosedCount,
MIN(CASE WHEN fd.name = 'bug_status' AND bugs_activity.added = 'VERIFIED' THEN bug_when ELSE NULL END) AS verifiedDate,
MIN(CASE WHEN fd.name = 'bug_status' AND bugs_activity.added = 'CLOSED' THEN bug_when ELSE NULL END) AS closedDate
FROM bugs_activity
INNER JOIN bugs bug
ON bugs_activity.bug_id = bug.bug_id
INNER JOIN fielddefs fd
ON bugs_activity.fieldid = fd.id
WHERE
(bugs_activity.bug_when BETWEEN '2015-09-01' AND #EndDate)
AND (Keywords LIKE '%Region:Europe%')
AND NOT (Keywords LIKE '%Report:DevProcess%')
GROUP BY bug_id
HAVING
ClosedCount > 0
AND (
(verifiedDate IS NOT NULL AND verifiedDate >= #StartDate)
OR (verifiedDate IS NULL AND (closedDate IS NOT NULL AND closedDate >= #StartDate))
)
Additional info from questions:
Linqpad SQL talking to MySQL DB
From linqpad - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UPDATE bugs SET bug.keywords = CONCAT(bug.keywords, ', Report:DevProcess')' at line 20
I removed GroupBy line, same error.
CONCAT is what a web search tells me How to prepend a string to a column value in MySQL?
In the selected "bugs" I want to "UPDATE bugs SET bug.keywords = CONCAT(bug.keywords, ', Report:DevProcess') "
Bugzilla has historically for a long time used multiple keywords. It is what it is whether good or bad.
== 31/05/2016 update ==
I simplified the query and got past the syntax error, however no update. I confirmed account had DB write access by using the read account which produced an access denied error.
-- this shows the one record
SELECT bug_id
FROM bugs
WHERE (bugs.bug_status = 'VERIFIED') AND (bugs.status_whiteboard LIKE '%Leiden%') and (bugs.keywords LIKE '%Region:Europe%') AND NOT (bugs.keywords LIKE '%Report:DevProcess%')
-- this runs without an error but shows no records updated
UPDATE bugs SET bugs.keywords = CONCAT(bugs.keywords, ', Report:DevProcess')
WHERE (bugs.bug_status = 'VERIFIED') AND (bugs.status_whiteboard LIKE '%Leiden%') and (bugs.keywords LIKE '%Region:Europe%') AND NOT (bugs.keywords LIKE '%Report:DevProcess%')
The simpler syntax does "work", i.e. no syntax error however the write did not work initially. This turned out to be because the keyword schema required the keyword to be pre-defined. Adding the keyword in resulting in the record being updated.
-- this runs without an error but shows no records updated
UPDATE bugs SET bugs.keywords = CONCAT(bugs.keywords, ', Report:DevProcess')
WHERE (bugs.bug_status = 'VERIFIED') AND (bugs.status_whiteboard LIKE '%Leiden%') and (bugs.keywords LIKE '%Region:Europe%') AND NOT (bugs.keywords LIKE '%Report:DevProcess%')

IF condition in mysql

I have a contact table I wish to query when a certain condition exists. I tried the query below but am getting a syntax error.
SELECT *
FROM contact_details
WHERE contactDeleted` =0
AND IF ( contactVisibility = "private"
, SELECT * FROM contact_details
WHERE contactUserId = 1
, IF( contactVisibility = "group"
, SELECT * FROM contact_details
WHERE contactGroup = 3
)
)
If I'm understanding your question correctly (which is difficult with the lack of info you've provided. Sample datasets and expected outcomes are typically helpful), then I don't believe you need IFs at all for what you want. The following will return contacts that are not deleted and who either have (visibility = "private" and userId = 1) OR (visibility = "group" and group = 3)
SELECT *
FROM contact_details
WHERE contactDeleted = 0
AND (
(contactVisibility = "public")
OR
(contactVisibility = "private" AND contactUserId = 1)
OR
(contactVisibility = "group" AND contactGroup = 3)
)
I am assuming you want to use the IF() function and not the statement which is for stored functions..
Refer to this link for more information on that.
Notice that you have put 2 select statements in there, where the custom return values are supposed to be. So you are returning a SELECT *... now notice that in your upper level sql statement you have an AND.. so you basically writing AND SELECT *.. which will give you the syntax error.
Try using .. AND x IN (SELECT *) .. to find if x is in the returned values.
Let me also list this link to make use of an existing and well written answer which may also applicable to your question.

MySQL Left Join, SELECT a field either from one or the other if null

I am trying to LEFT JOIN 2 tables. which is working out fine. But i am getting back two sets of fields named setting_value. iam trying to get tblSettings.setting_value only if tblAgencySettings.setting_value is NULL. How would i go about doing this? I know i can rename the fields, then in PHP i can check the tblAgencySettings.setting_value and if NULL then grab the tblSettings.setting_value but i prefer to keep this at MySQL.
SELECT `tblSettings`.`id`, `tblSettings`.`setting_name`,
`tblSettings`.`setting_value`, `tblAgencySettings`.`setting_value`
FROM `tblSettings` LEFT JOIN `tblAgencySettings`
ON `tblSettings`.`id` = `tblAgencySettings`.`setting_id`
AND `tblAgencySettings`.`agency_id` = '1'
WHERE `tblSettings`.`changeable` = '1'
slight issue i just noticed. i failed to mention this. if tblAgencySettings.setting_value does have a value. but changeable is not 1 then just select tblSettings.setting_value
Just add a COALESCE:
SELECT `tblSettings`.`id`, `tblSettings`.`setting_name`,
COALESCE(`tblAgencySettings`.`setting_value`, `tblSettings`.`setting_value`)
FROM `tblSettings` LEFT JOIN `tblAgencySettings`
ON `tblSettings`.`id` = `tblAgencySettings`.`setting_id`
AND `tblAgencySettings`.`agency_id` = '1'
WHERE `tblSettings`.`changeable` = '1'
The COALESCE function returns the first non-NULL value you give it so this:
COALESCE(`tblAgencySettings`.`setting_value`, `tblSettings`.`setting_value`)
Will be tblAgencySettings.setting_value if that's not NULL and tblSettings.setting_value if tblAgencySettings.setting_value is NULL.
If tblAgencySettings.setting_value can also be zero and you want to ignore that as well as NULL, then you could use this instead of the COALESCE above:
COALESCE(
IF(`tblAgencySettings`.`setting_value` = 0, NULL, `tblAgencySettings`.`setting_value`),
`tblSettings`.`setting_value`
)
The IF returns the second argument if the first is true and the third if the first argument is false so the above use converts zero to NULL. Or, you could go all the way to a CASE statement:
case
when `tblAgencySettings`.`setting_value` = 0 then `tblSettings`.`setting_value`
when `tblAgencySettings`.`setting_value` IS NULL then `tblSettings`.`setting_value`
else `tblSettings`.`setting_value`
end
Change your SQL Statement to this:
SELECT `tblSettings`.`id`, `tblSettings`.`setting_name`,
CASE WHEN `tblSettings`.`setting_value` IS NULL THEN `tblAgencySettings`.`setting_value`
ELSE `tblSettings`.`setting_value` END AS `setting_value`
FROM `tblSettings` LEFT JOIN `tblAgencySettings`
ON `tblSettings`.`id` = `tblAgencySettings`.`setting_id`
AND `tblAgencySettings`.`agency_id` = '1'
WHERE `tblSettings`.`changeable` = '1'
Here's a link to MYSQL CASE Statement for your reference.