Delphi, FireDAC, MySQL Query - mysql

qClient.SQL.Clear;
qClient.SQL.Text := 'Select C.Lastname,C.Firstname,C.Clino,C.Address,' +
'C.City,C.State,C.Zip,C.Phone,C.HerCell,C.HisCell,' +
'C.Texting,C.Since,C.Selected,' +
'SUM( I.Charges - I.Discount ) as Revenue ' +
'from Client C join Invoice I ' +
'on I.Clino = C.Clino ' +
'where I.Date between :S and :E ' +
'and I.Inv = true ' +
'group by C.Clino ' +
'order by Revenue desc ';
qClient.ParamByName('S').AsDate := dStart;
qClient.ParamByName('E').AsDate := dEnd;
qClient.DetailFields := 'Clino';
qClient.Open();
How can I modify the above code so that the query includes only 'Revenue' values over a minimum (like maybe 1000)? It currently includes all clients.
Thanks,
Spyke

You need a HAVING clause:
qClient.SQL.Text := 'Select C.Lastname,C.Firstname,C.Clino,C.Address,' +
'C.City,C.State,C.Zip,C.Phone,C.HerCell,C.HisCell,' +
'C.Texting,C.Since,C.Selected,' +
'SUM( I.Charges - I.Discount ) as Revenue ' +
'from Client C join Invoice I ' +
'on I.Clino = C.Clino ' +
'where I.Date between :S and :E ' +
'and I.Inv = true ' +
'group by C.Clino ' +
'having Revenue > 1000 ' +
'order by Revenue desc ';
The HAVING clause applies conditions and filters the results of the query after the aggregation.
In this case Revenue is an aggregated column and could not be used in a WHERE clause which also filters a query, because the conditions of the WHERE clause are applied before the aggregation.

Related

MySQL: Optimizing queries

How can I write this in a more optimized way?
SELECT week_day
, SUM(min_0 + min_1 + min_2 + min_3)
/ (SELECT SUM(min_0 + min_1 + min_2 + min_3)
FROM Hotel.RegIn) * 100 AS MIN_PERCENTAGE
FROM Hotel.RegIn
WHERE week_day = "Wednesday"
GROUP
BY week_day;
I'd write it as below:
SELECT
"Wednesday",
100 * SUM((week_day = "Wednesday") * (min_0 + min_1 + min_2 + min_3))
/ SUM(min_0 + min_1 + min_2 + min_3) AS MIN_PERCENTAGE
FROM Hotel.RegIn
;
or if you can use multiple statements, another one with easier filters:
SET #var_all_day_total :=
(SELECT SUM(min_0 + min_1 + min_2 + min_3) FROM Hotel.RegIn) / 100;
SELECT
week_day,
SUM(min_0 + min_1 + min_2 + min_3) / #var_all_day_total AS MIN_PERCENTAGE
FROM Hotel.RegIn
-- WHERE week_day = "Wednesday"
GROUP BY
week_day
;
The idea usually is not to redundantly calculate the same values more than once.
You should use derived table in the FROM clause. This way the subquery will be evaluated only once.
SELECT
week_day,
SUM(min_0 + min_1 + min_2 + min_3) / RegInSum.sum_all * 100 AS MIN_PERCENTAGE
FROM
Hotel.RegIn,
(SELECT
SUM(min_0 + min_1 + min_2 + min_3) as sum_all
FROM
Hotel.RegIn) as RegInSum
WHERE week_day = "Wednesday"
GROUP BY week_day;
Note that as far as you restrict your query only to one day of week, you won't get any performance gain by rewriting the query, because the subquery will be evaluated only once in both cases.
See CTE (Common Table Expressions) for more readable syntax of derived tables in newer versions of MySQL.

Creating a SQL string to use with exec sp_executesql #sql

I am having difficulty formatting a string to be used with SP_executesql. I keep getting the following error:
Msg 102, Level 15, State 1, Line 144
Incorrect syntax near '))'
Line 144 is the last line of this code
All variables were declared above
set #Sql = #Sql + ' select distinct provider_id, ' + #changestring + ', null,'''
+ 'case when ' + #changestring + '= 6 then ds.excldate +
else +
CONVERT(varchar(20),' + GETDATE() + ') end as '+ '''Effective_Date'
+ ''', null,1,' + #username + '''
+ ,NULL,' + CONVERT(varchar(20), GETDATE()) + ''',''' + CONVERT(varchar(20), GETDATE()) + ''', '''+ #username + '''' +
' from (
select distinct provider_id
FROM provider pv WHERE provider_id In (select Provider_id from dbo.##sanctiontermswid )) ds
where ds.provider_id not in (
select provider_id from provider_status ps where ps.provider_id in (
select distinct provider_id
FROM Provider pv WHERE provider_id IN (select Provider_ID from ##sanctiontermswid ) and ps.provider_status_type_id = ' + #changestring + '))'
It looks like you are forgetting to convert the first GETDATE() to varchar.
Was able to finally format my SQL. The problem was in formatting the case statement.
set #Sql = #Sql + 'select distinct DS.provider_id, ' + #changestring + ', null, case when ''' + #changeString + '''!= ''6'' then '''
+ CONVERT(varchar(20), GETDATE()) + ' '' else CONVERT(DATE,DS.exCldate) end as ''Effective_date'''
+ ', null,1,'''+ #username + '''
,NULL,''' + CONVERT(varchar(20), GETDATE()) + ''',''' + CONVERT(varchar(20), GETDATE()) + ''', '''+ #username + '''' +
' from (
select distinct PV.provider_id, T1.EXCLDATE
FROM provider pv
JOIN dbo.##tmpSanctions T1 ON PV.PROVIDER_ID=T1.PROVIDER_id
) ds
where ds.provider_id not in (
select provider_id from provider_status ps where ps.provider_id in (
select distinct provider_id
FROM Provider pv WHERE provider_id IN (select Provider_ID from dbo.##tmpSanctions ) and ps.provider_status_type_id= '+ #changestring + ' and ps.effective_thru is null))'

How to count the occurrence of specific words in a Mysql db row?

I'm quite new to MySQL. I require to count the number of occurrences of specific words in a MySQL table/columns.
I came across the following code through another post #Raging Bull, which only provides the count of one specific word.
SELECT name,(CHAR_LENGTH(description)-
CHAR_LENGTH(REPLACE(description,' is ','')))/CHAR_LENGTH(' is ') AS
TotalCount
FROM TableName
GROUP BY name
Could someone help me to align it for multiple words to be counted. For example, I want to count "is", "as", "was", "how".
MySQL is not designed for this sort of thing. However, you can just add the values together. I thing the correct method is like this;
select ( (length(concat(' ', description, ' ')) - length(replace(concat(' ', description, ' '), ' is ', '')) / length(' is ') +
(length(concat(' ', description, ' ')) - length(replace(concat(' ', description, ' '), ' as ', '')) / length(' as ') +
(length(concat(' ', description, ' ')) - length(replace(concat(' ', description, ' '), ' was ', '')) / length(' was ') +
(length(concat(' ', description, ' ')) - length(replace(concat(' ', description, ' '), ' how ', '')) / length(' how ')
)
from t ;
Note the use of spaces at the beginning and end to capture words at the beginning and end of the description. Also, this assumes that only spaces are used for separating words.
Try using LENGTH instead of CHAR_LENGTH and truncate spaces from String, e.g.:
SELECT name,
ROUND (
(
LENGTH(description)
- LENGTH(REPLACE(description, "is", ""))
) / LENGTH("is")
) AS count
FROM TableName
update
To count multiple words, you can write simillar ROUND queries and add them together, e.g.:
SELECT name,
SELECT(
ROUND((LENGTH(description)- LENGTH(REPLACE(description, "is", "")) ) / LENGTH("is")) +
ROUND((LENGTH(description)- LENGTH(REPLACE(description, "This", "")) ) / LENGTH("This")) +
ROUND((LENGTH(description)- LENGTH(REPLACE(description, "That", "")) ) / LENGTH("That"))
) AS `count`
FROM TableName
update 2
Here's the query to get the counts as individual columns:
SELECT name,
ROUND((LENGTH(description)- LENGTH(REPLACE(description, "is", "")) ) / LENGTH("is")) AS 'is count',
ROUND((LENGTH(description)- LENGTH(REPLACE(description, "this", "")) ) / LENGTH("this")) AS 'this count',
ROUND((LENGTH(description)- LENGTH(REPLACE(description, "by", "")) ) / LENGTH("by")) AS 'by count'
FROM TableName
update 3
Below is the query to get aggregated counts for words:
SELECT 'is', SUM(ROUND((LENGTH(description)- LENGTH(REPLACE(description, "is", "")) ) / LENGTH("is"))) AS `count` FROM TableName
UNION
SELECT 'this', SUM(ROUND((LENGTH(description)- LENGTH(REPLACE(description, "this", "")) ) / LENGTH("this"))) AS `count` FROM TableName
UNION
SELECT 'by', SUM(ROUND((LENGTH(description)- LENGTH(REPLACE(description, "by", "")) ) / LENGTH("by"))) AS `count` FROM TableName
Here's the SQL Fiddle.
select count(adm_no) from class_manager
Try that where adm_no is the column name and class_manager is the table

Order By with Union Sql Server 2008

CREATE PROCEDURE [dbo].[spReport]
#FromDate DATETIME = NULL,
#ToDate DATETIME = NULL,
#TenantID int ,
#BusinessUnitId int
AS
BEGIN
Declare #listStr Varchar(max), #listValue Varchar(max)
Select
#listStr = COALESCE(#listStr+',' ,'') + FieldLabel
From
(Select Distinct Top 100
FieldLabel, ControlTypeId
From
PaymentCustomFieldDefinitions PCFD
Inner Join
Product P On P.Id = PCFD.ProductId
Where
P.TenantId = #TenantId
Order By
ControlTypeId Desc) R
Set #listStr = ',' + #listStr
Set #listStr = IsNull(#listStr, '')
Select
'Confirmation Number,Business Unit,Bank Account,Merchant Account,Product Name,Payment Date,Payment Time,Total Amount,Status,First Name,Last Name,Payment Method' + #listStr
Union
SELECT
p.ConfirmationNumber + ',' + bu.Name + ',' + p.TenantBankAccountName + ',' + Case When ma.Name IS NULL then '' ELSE ma.Name END + ',' + pd.Name + ',' +
cast(P.PaymentDate as Varchar(11)) + ',' + convert(VARCHAR(8), P.PaymentDate,108) + ',' + Cast(p.TotalDue As Varchar(20)) + ',' + p.PaymentStatusText + ',' + p.PayorFirstName + ',' + p.PayorLastName + ',' + p.PaymentMethodText + ',' + [dbo].[GetPaymentReferenceAndCustomFields](p.Id,#listStr)
FROM
Payment p
INNER JOIN
Product pd ON p.ProductId = pd.Id
INNER JOIN
BusinessUnit bu ON pd.BusinessUnitId = bu.Id
INNER JOIN
ProductDetailPayment pdp ON p.ProductId = pdp.ProductId
LEFT OUTER JOIN
MerchantAccount ma ON ma.Id = pdp.MerchantAccountId
WHERE
p.PaymentDate BETWEEN #FromDate AND #ToDate
AND p.TenantId = #TenantId AND pd.BusinessUnitId= #BusinessUnitId
ORDER BY
p.ProductId desc
END
Getting this error when using Order by :
Msg 4104, Level 16, State 1, Procedure spReport, Line 41
The multi-part identifier "p.ProductId" could not be bound.
Msg 104, Level 16, State 1, Procedure spQueryPaymentDetailReport, Line 41
ORDER BY items must appear in the select list if the statement contains a UNION, INTERSECT or EXCEPT operator.
You can't reference p.ProductId in the ORDER BY because the first subquery doesn't have a p dataset.
You can't reference a ProductId column in the ORDER BY because there's no column by that name in the combined result set.
To solve these issues, you could add a ProductId column and, if the final output must contain a single column like in your query, use a derived table:
SELECT
p.CSV
FROM (
Select
ProductId = 2147483647,
CSV = 'Confirmation Number,Business Unit,Bank Account,Merchant Account,Product Name,Payment Date,Payment Time,Total Amount,Status,First Name,Last Name,Payment Method' + #listStr
Union
SELECT
p.ProductId,
p.ConfirmationNumber + ',' + bu.Name + ',' + p.TenantBankAccountName + ',' + Case When ma.Name IS NULL then '' ELSE ma.Name END + ',' + pd.Name + ',' +
cast(P.PaymentDate as Varchar(11)) + ',' + convert(VARCHAR(8), P.PaymentDate,108) + ',' + Cast(p.TotalDue As Varchar(20)) + ',' + p.PaymentStatusText + ',' + p.PayorFirstName + ',' + p.PayorLastName + ',' + p.PaymentMethodText + ',' + [dbo].[GetPaymentReferenceAndCustomFields](p.Id,#listStr)
FROM
Payment p
INNER JOIN
Product pd ON p.ProductId = pd.Id
INNER JOIN
BusinessUnit bu ON pd.BusinessUnitId = bu.Id
INNER JOIN
ProductDetailPayment pdp ON p.ProductId = pdp.ProductId
LEFT OUTER JOIN
MerchantAccount ma ON ma.Id = pdp.MerchantAccountId
WHERE
p.PaymentDate BETWEEN #FromDate AND #ToDate
AND p.TenantId = #TenantId AND pd.BusinessUnitId= #BusinessUnitId
) p
ORDER BY
p.ProductId desc
;
The first row is assigned the MaxInt ID value because, as I understand, it is the header row and must go first according to the specified ORDER BY p.ProductId DESC clause (and because I've assumed the ProductId is an int, of course).

Error with CTE . Could any one help me correct the below error

I am writing below function to return Suffix passing name as parameter. I made possible cases of suffix exsist in name as common table expression and trying to compare with that. Could any one explain me the proper way of doing it.
Alter function S (#Name varchar(100))
returns varchar(25)
as
begin
declare #Suffix varchar(25)
WITH SearchTerms(Term)
AS (SELECT ' I '
UNION ALL
SELECT ' II '
UNION ALL
SELECT ' III '
UNION All
SELECT ' MD '
UNION All
SELECT ' M.D '
UNION All
SELECT ' M.D. '
UNION All
SELECT ' D.O '
UNION All
SELECT ' D.O. '
UNION All
SELECT ' DO '
) ;
set #Suffix = (select Term from SearchTerms where Charindex(Term,#Name) > 0)
return #Suffix
end
Error message.
Msg 319, Level 15, State 1, Procedure S, Line 6
Incorrect syntax near the keyword 'with'. If this statement is a common table expression,
an xmlnamespaces clause or a change tracking context clause, the previous statement must
be terminated with a semicolon.
I see it now, you have a semi-colon at the end of your CTE declaration. You can't do that since that terminates the statement. Try this:
ALTER FUNCTION dbo.S(#Name varchar(100))
RETURNS VARCHAR(25)
AS
BEGIN
DECLARE #Suffix VARCHAR(25);
WITH SearchTerms(Term) AS
(
SELECT ' I '
UNION ALL SELECT ' II '
UNION ALL SELECT ' III '
UNION ALL SELECT ' MD '
UNION ALL SELECT ' M.D '
UNION ALL SELECT ' M.D. '
UNION ALL SELECT ' D.O '
UNION ALL SELECT ' D.O. '
UNION ALL SELECT ' DO '
)
SELECT #Suffix = Term
FROM SearchTerms
WHERE CHARINDEX(Term, ' ' + #Name + ' ') > 0;
RETURN (LTRIM(RTRIM(#Suffix)));
END
GO
EDIT based on new information, here is a table-valued function that returns all results:
CREATE FUNCTION dbo.T
(
#Name VARCHAR(100)
)
RETURNS TABLE
AS
RETURN
(
SELECT
Term = CONVERT(VARCHAR(25), LTRIM(RTRIM(Term)))
FROM
(
SELECT Term = ' I '
UNION ALL SELECT ' II '
UNION ALL SELECT ' III '
UNION ALL SELECT ' MD '
UNION ALL SELECT ' M.D '
UNION ALL SELECT ' M.D. '
UNION ALL SELECT ' D.O '
UNION ALL SELECT ' D.O. '
UNION ALL SELECT ' DO '
) AS Terms
WHERE CHARINDEX(Term, ' ' + #Name + ' ') > 0
);
GO
SELECT Term FROM dbo.T('Terry Allen MD III');