How can I implement below logic in where clause ?
below is the scenario.
IF #include_prime = 'YES'
Then result set should contain Promo_records along with non_prime_records
IF #include_prime = 'NO'
Then result set should contain only non_prime_records
I have tried as below, for both "Yes" and "No" selection I am getting same number of records
`DECLARE
#weeks INT = 2,
#week_ending DATE = '12/03/2022',
#include_prime CHAR(3)='YES'
BEGIN
SELECT
[PRType],
[PRName],
[PRNumber],
[PROffice],
[PRStudio],
[Manager],
[WeekEndDate]
FROM Source_table
WHERE
Source_table.[WeekEndDate] BETWEEN #week_ending AND DATEADD("WEEK",CAST(#weeks AS INT),#week_ending)
AND
( ( #include_prime = 'Yes'
OR Source_table.[PRType] = 'Prime'
)
OR
( #include_prime = 'No'
AND Source_table.[PRType] <> 'Prime'
)
END`
This is the first time I am attempting to parse a variable to a CF query, but I have run into a few little issues.
In summary, I am creating a pivot table of sales by operators by week. Manually, no hassle, but I only want a subset of weeks, not all. Again, no real problem if I want hardcoded weeks, but the problem comes in when I try and parse a week number to the SQL query to create the subset of dynamic weeks.
The CFDUMP shows me that the query is executing based on what I am sending to it, but when it comes to outputting the value of the field (the week), it takes the variable name value, and not the field value if that makes sense?
I know that I shouldn't be having field names as values, but I still tryingh to test right now. With the manual query, I prefix the week number with a 'W' e.g. W9, but when I try and do that I get
MANUAL QUERY
SELECT UserName,
ISNULL([W6], 0) AS [W6],
ISNULL([W7], 0) AS [W7],
ISNULL([W8], 0) AS [W8],
ISNULL([W9], 0) AS [W9],
ISNULL([W10], 0) AS [W10]
FROM ( SELECT CASE
WHEN SUBSTRING(Username, 1, 3) = 'd.S' THEN 'DS'
WHEN SUBSTRING(Username, 1, 3) = 'p.R' THEN 'PR'
WHEN SUBSTRING(Username, 1, 3) = 'j.G' THEN 'JG'
WHEN SUBSTRING(Username, 1, 3) = 'b.c' THEN 'BC'
ELSE 'Other' END AS Username,
CONCAT('W', DATEPART(isowk, ERCFullAuditDate)) as XWeek,
COUNT(1) [SalesCount]
FROM [ERC-Transactions].[dbo].[ERC-Audit]
WHERE ( ERCModule = 'Carriage Return on Account'
AND ERCFullAuditDate >= DATEADD(week, -4, GETDATE())
OR ( ERCFullAuditDate <= DATEADD(week, -52, convert(datetime, GETDATE()))
and ERCFullAuditDate >= DATEADD(week, -56, convert(datetime, GETDATE()))))
GROUP BY DATEPART(isowk, ERCFullAuditDate),
UserName) ST
PIVOT ( SUM(SalesCount)
for XWeek in ([W6], [W7], [W8], [W9], [W10])) as StorePivot
The above yields this result.
THE COLDFUSION DYNAMIC QUERY
Now when I try and do the same, but by parsing variables to the query, the CFDUMP yields the correct values, but as I said, when I try and output this, I get the field name and not the value.
To be honest, I have two issues here in that I need to address. The variable field name, but also when I come to adding the concatenation of 'W' to the week number, I am seeing an 'Error converting data type nvarchar to int.' I think I may need a cfqueryparam, but I am not sure.
<cfset WEEK_2 = DATETImeFormat(DateAdd("ww",-2,now()),"w")>
<cfoutput>Week: #WEEK_2#</cfoutput> (This is the value of the WEEK_2 variable)<br>
<cfset XX = "">
<cfset XX = XX & "SELECT UserName, ">
<cfset XX = XX & "ISNULL([#WEEK_2#], 0) AS [#WEEK_2#] ">
<cfset XX = XX & "FROM ( SELECT CASE ">
<cfset XX = XX & "WHEN SUBSTRING(Username,1,3) = 'd.S' THEN 'DS' ">
<cfset XX = XX & "WHEN SUBSTRING(Username,1,3) = 'p.R' THEN 'PR' ">
<cfset XX = XX & "WHEN SUBSTRING(Username,1,3) = 'j.G' THEN 'JG' ">
<cfset XX = XX & "WHEN SUBSTRING(Username,1,3) = 'b.c' THEN 'BC' ">
<cfset XX = XX & "ELSE 'Other' END AS Username, ">
<cfset XX = XX & "DATEPART(isowk, ERCFullAuditDate) as XWeek, ">
<cfset XX = XX & "COUNT(1) [SalesCount] ">
<cfset XX = XX & "FROM [EBS-ERC-Transactions].[dbo].[ERC-Audit] ">
<cfset XX = XX & "WHERE ( ERCModule = 'Carriage Return on Account' ">
<cfset XX = XX & "AND ERCFullAuditDate >= DATEADD(week, -4, GETDATE()) ">
<cfset XX = XX & "OR ( ERCFullAuditDate <= DATEADD(week, -52, convert(datetime, GETDATE())) ">
<cfset XX = XX & "and ERCFullAuditDate >= DATEADD(week, -56, convert(datetime, GETDATE())))) ">
<cfset XX = XX & "GROUP BY DATEPART(isowk, ERCFullAuditDate), ">
<cfset XX = XX & "UserName) ST ">
<cfset XX = XX & "PIVOT ( SUM(SalesCount) ">
<cfset XX = XX & "for XWeek in ([#WEEK_2#])) as StorePivot ">
<cfquery name = "QueryTest" dataSource = "EBSERC">
#PreserveSingleQuotes(XX)#
</cfquery>
<br>
<cfoutput Query="QueryTest">
#UserName#, #WEEK_2#<br>
</cfoutput>
<br>
<cfdump var="#QueryTest#" />
And this is the result ...
Ultimately, as mentioned before, I want to concatenate 'W' to the week number field.
Any guidance or a steer in the right direction will be VERY appreciated and thanks for your time.
Thank you very much for reading.
This is too long for comments.
Since the column labels are dynamic and closely bound to the database, I'd probably do this all on the database side. Preferably inside a stored procedure.
If you're using SQL Server 2017+, a CTE could be used to generate the weeks within the desired date range. Then STRING_AGG() used to convert the results into comma separated lists.
; WITH dates AS (
-- Generate range between -56 and -52 weeks ago
SELECT DateAdd(wk, -56, GETDATE()) AS WeekDate
UNION ALL
SELECT DateAdd(wk, 1, WeekDate)
FROM dates
WHERE DateAdd(wk, 1, WeekDate) <= DateAdd(wk, -52, GETDATE())
)
, dateLabels AS (
-- extract week number and construct label "W1","W2",etc..
SELECT DATEPART(isowk, WeekDate) AS WeekNum
, QUOTENAME( CONCAT('W', DATEPART(isowk, WeekDate) )) AS WeekLabel
FROM dates
)
-- convert to comma separated lists
SELECT STRING_AGG( WeekLabel, ',')
WITHIN GROUP (ORDER BY WeekNum) AS PivotColumns
, STRING_AGG( CONCAT('ISNULL(', WeekLabel, ',0) AS ', WeekLabel ), ',')
WITHIN GROUP (ORDER BY WeekNum) AS SelectColumns
FROM dateLabels
;
The results would look like this (minus any line wrapping)
PivotColumns
SelectColumns
[W6],[W7],[W8],[W9],[W10]
ISNULL([W6],0) AS [W6],ISNULL([W7],0) AS [W7],ISNULL([W8],0) AS [W8],ISNULL([W9],0) AS [W9],ISNULL([W10],0) AS [W10]
Then simply plug the two lists into the SQL query. In CF:
<cfscript>
// ...
sqlString = "
SELECT UserName
, #SelectColumns#
FROM (
...
) ST
PIVOT
(
SUM(SalesCount)
FOR XWeek IN ( #PivotColumns# )
) AS StorePivot
";
qPivot = queryExecute( sqlString );
// ...
</cfscript>
Results:
SELECT UserName
, ISNULL([W6],0) AS [W6]
, ISNULL([W7],0) AS [W7]
, ISNULL([W8],0) AS [W8]
, ISNULL([W9],0) AS [W9]
, ISNULL([W10],0) AS [W10]
FROM (
...
) ST
PIVOT (
SUM(SalesCount)
FOR XWeek IN (
[W6],[W7],[W8],[W9],[W10]
)
) AS StorePivot
WHERE oh where are the parentheses?
A few observations about the original query:
The current WHERE clause is incorrect. When mixing AND/OR operators, parentheses must be used to ensure the order of operations. Conceptually, the current query is doing this:
WHERE Condition1 AND Condition2 OR Condition3
It should be using parentheses here:
WHERE Condition1 AND ( Condition2 OR Condition3 )
GETDATE() already returns a datetime value, so there's no need to convert it to a datetime again here:
DATEADD(week, -52, convert(datetime, GETDATE()))
Lastly, there shouldn't be a need for all the concatenation. Strings can usually span multiple lines, and there's always cfsavecontent if needed. Removing all the & will greatly improve readability.
If you're trying to copy the SQL exactly I think you missed the 'W' in the cfset at the top:
<cfset WEEK_2 = 'W' & DATETImeFormat(DateAdd("ww",-2,now()),"w")>
Outputs:
Week: W9 (This is the value of the WEEK_2 variable)
You have this command:
<cfset XX = XX & "ISNULL([#WEEK_2#], 0) AS [#WEEK_2#] ">
Since the week_2 variable has a value of 9, when that command gets executed, it becomes this:
<cfset XX = XX & "ISNULL([9], 0) AS [9] ">
and your query becomes
select username
, 9 as 9
from etc
You are going to have to put some more thought into generating your week numbers.
I have the following code where i am tryin to use mod operator to list 5 items on the line and then move to next line, On the single line it should display 5 items and then in next line, it should display the remaining items, if the remaining items are more than 5, it should go to 3rd line then
i am trying this code: but it not doing anything
<cfset items = "1,2,3,4,5,6,7,8,9,0">
<cfif listLen(items) mod 5>
<cfoutput>
#items##Chr(10)##chr(13)#TEST
</cfoutput>
</cfif>
it is displaying all in one line
There are a couple of things wrong with your code.
You are not looping over the list to display each item.
Chr(10) and Chr(13) (linefeed and carriage return) do not display in HTML and your browser.
I modified your code like this:
<cfset counter = 0>
<cfset items = "1,2,3,4,5,6,7,8,9,0,a,b,c">
<cfloop index="thisItem" list="#items#">
<cfset counter = counter + 1>
<cfif counter mod 5>
<cfoutput>#thisItem#, </cfoutput>
<cfelse>
<cfoutput>#thisItem#<br></cfoutput>
</cfif>
</cfloop>
Try it here
and here is an example of that same logic using cfscript syntax:
<cfscript>
counter = 0;
items = "1,2,3,4,5,6,7,8,9,0,a,b,c";
for (counter = 1; counter lte listlen(items); counter++) {
if (counter mod 5) {
writeOutput('#listGetAt(items,counter)#, ');
} else {
writeOutput('#listGetAt(items,counter)#<br>');
}
}
</cfscript>
Try it here
The code I have given you here can be cleaned up a bit but hopefully it is easy to understand for you.
Here is another approach if you are on CF10+:
<cfscript>
// Items List
items_list = "1,2,3,4,5,6,7,8,9,0,a,b,c";
// Convert to array
items_array = items_list.listToArray( "," );
// Item Count
itemCount = arrayLen( items_array );
// Display
for ( i = 1; i <= itemCount; i += 5) {
writeOutput( items_array.slice( i, i + 5 - 1 > itemCount ? itemCount % 5 : 5 ).toList( "," ) & "<br>" );
}
</cfscript>
Here is the TryCF.
Here is another approach.
<cfset items = "1,2,3,4,5,6,7,8,9,0,a,b,c">
<cfoutput>
<cfloop from="1" to="#listLen(items)#" index="i">
#listGetAt(items,i)#
<cfif i mod 5 eq 0>
<br>
<cfelseif i neq listLen(items)>
,
</cfif>
</cfloop>
</cfoutput>
Results in
1 , 2 , 3 , 4 , 5
6 , 7 , 8 , 9 , 0
a , b , c
Given the array below, how do I convert it to a simple list of values?
<cfdump var="#arguments.ServiceTextArray#">
Array Elements:
1 3567_no
2 3584_yes
3 3642_yes
4 3643_yes
5 3644_no
6 3645_no
7 3646_no
Specifically, how do I extract values with the "yes" suffix and produce a list like this?
3584,3642,3643
Thanks in advance.
Would this help? There will always be better solution than this.
<cfset myList = "">
<cfloop from="1" to="#Arraylen(myArray)#" index="index">
<Cfif right(myArray[index],3) EQ "yes">
<cfset myList = listAppend(myList, listFirst(myArray[index], '_'))>
</Cfif>
</cfloop>
<cfoutput>#myList#</cfoutput>
This is partly an extension to Henry answer but should be exactly what your after:
<cfscript>
tmpArray = ['567_no','584_yes','3642_yes','3643_yes','3644_no','3645_no','3646_no'];
list = "";
for (item in tmpArray)
if (listLast(item, "_") == "yes")
list = listAppend(list, listFirst(item, "_"));
writeDump(list);
var list = "";
for (item in array)
if (ListLast(item, "_"))
list = listAppend(list, val(item));
Using the Underscore.cfc library (CF 10 only):
filteredArray = _.filter(arguments.ServiceTextArray, function(val) {
return (val contains 'yes');
});
resultArray = _.map(filteredArray, function(val) {
return left(val, 4);
});
list = arrayToList(resultArray);
(I created this library, BTW)