Can get the Union to work correctly - sql

Select CorpID,
Convert(VarChar(2),Month(E.BeginDate)) + '/' + Convert(VarChar(4),Year(E.BeginDate)),
Count(Year(e.BeginDate)) As 'total Screen'
--Count(Month(E.CurrentBeginDate))
From dbo.NonCalls E
Where E.BeginDate between {d'2013-01-01'} and {d'2013-12-31'}
Group By CorpID, Year(E.BeginDate),Month(E.BeginDate)
Union ALL
Select CorpID,
Convert(VarChar(2),Month(E.CurrentBeginDate)) + '/' + Convert(VarChar(4),Year(E.CurrentBeginDate)),
Count(Year(e.CurrentBeginDate)) As 'total Screen'
--Count(Month(E.CurrentBeginDate))
From dbo.Employee E
Where E.CurrentBeginDate between {d'2013-01-01'} and {d'2013-12-31'}
Group By CorpID, Year(E.CurrentBeginDate),Month(E.CurrentBeginDate)
--Order By CorpID, Year(E.CurrentBeginDate), Month(E.CurrentBeginDate)
I change my code to this and now I get the numbers that i was looking for the only problem is that it's not sorted i need it to sorted by Corpid and then by date 01-02-03 etc I'm not quite sure
how to get that accomplish any help would be greatly apreciated.

You have 2 CurrentBeginDate in your second part of the UNION causing that one to return 5 columns, but the first part only 4 columns
SELECT
CorpID ,
CurrentBeginDate <--HERE,
CONVERT(VARCHAR(2), MONTH(E.CurrentBeginDate)) + '/'
+ CONVERT(VARCHAR(4), YEAR(E.CurrentBeginDate)) AS CurrentBeginDate <--HERE,
COUNT(YEAR(e.CurrentBeginDate)) AS 'total Screen' ,
'' AS d1
As the error message says, for the union to work, it need the same amount of columns returned from all parts of the query.

As an answer to your "new question about sorting the now correctly unioned data:
You need to treat the unioned resultset as a derived table and select from it with your order. by.
SELECT *
FROM (<your unioned query)
ORDER BY CorpID
,Year(CurrentBeginDate)
,Month(CurrentBeginDate)
See here for more more complete discussion:
TSQL ORDER-BY with a UNION of disparate datasets

Related

SUM and GROUP BY a substring in Splice (NoSql)

I am trying to to run a query like the one below. The goal is to get the total activity count for every user_key but because the user_key has a complex structure and I need only the part after the '|' symbol I had to use a substring function. However, when I'm trying to run the query, I get the
error:
SQL Error [42Y36]: Column reference 'USER_KEY' is invalid, or is part of an invalid expression. For a SELECT list with a GROUP BY, the columns and expressions being selected may only contain valid grouping expressions and valid aggregate expressions.
The substring function works OK outside this query. Any workarounds for this problem? Using Splice Machine (NoSql)
SELECT
substr(user_key, instr(user_key,'|') + 1) AS new_user_key,
SUM(
CAST(
activity_count AS INTEGER
)
) AS Total
FROM
schema_name.table_name
GROUP BY
substr(user_key, instr(user_key,'|') + 1)
Your GROUP BY column needs to match the SELECT
SELECT
substr(user_key, instr(user_key,'|') + 1) AS new_user_key,
SUM(
CAST(
activity_count AS INTEGER
)
) AS Total
FROM
schema_name.table_name
GROUP BY
substr(user_key, instr(user_key,'|') + 1) AS new_user_key
I found the answer myself. I used a table subquery:
SELECT new_table.new_user_key, sum(new_table.total)
from
(
SELECT
substr(user_key, instr(user_key,'|') + 1) AS new_user_key,
CAST(activity_count AS INTEGER) AS Total
FROM schema_name.table_name
)
as new_table
GROUP BY
new_table.new_user_key
Let's hope someone will find this post useful and will save some time to him or her.

sql server using SUBSTRING with LIKE operator returns no results

I created this CTE that returns first and last names from 2 different tables. I would like to use the CTE to identify all of the records that have the same last names and the first name of one column starts with the same first letter of another column.
This is an example of the results of the CTE. I want the SELECT using the CTE to return only the highlighted results:
;WITH CTE AS
(
SELECT AD.FirstName AS AD_FirstName, AD.LastName AS AD_LastName, NotInAD.FirstName As NotInAD_FirstName, NotInAD.LastName As NotInAD_LastName
FROM PagingToolActiveDirectoryUsers AD JOIN
(
SELECT FirstName, LastName
FROM #PagingUsersParseName
EXCEPT
SELECT D.FirstName, D.LastName
FROM PagingToolActiveDirectoryUsers D
WHERE D.FirstName <> D.LastName AND D.LastName <> D.LoginName
AND D.LoginName LIKE '%[0-9]%[0-9]%'
) AS NotInAD ON NotInAD.LastName = AD.LastName
)
SELECT *
FROM CTE
WHERE (AD_LastName = NotInAD_LastName) AND (AD_FirstName LIKE ('''' + SUBSTRING(NotInAD_FirstName, 1, 1) + '%'''))
ORDER BY AD_LastName, AD_FirstName;
The result of this query returns no rows.
What am I doing wrong?
Thanks.
You're enclosing the string to be searched for with single-quotes, but it doesn't appear that the data in AD_FirstName has those single-quotes embedded in it. I suggest you replace the first line of the WHERE clause with
WHERE (AD_LastName = NotInAD_LastName) AND (AD_FirstName LIKE (SUBSTRING(NotInAD_FirstName, 1, 1) + '%'))
Best of luck.

Order by Function Results in Union Statement

I have a query that has multiple union statements where the last union statements results are derived from a function. I want to know how to sort the resultset based on the vchLastName of the function results. Here is the basis of the stored procedure.
select ID, objtype, Descr=coalesce(v.acctName, x.Descr), x.ihhid
from (
-----select statements----
UNION ALL
SELECT
pn.iPartyID,
'CONTACT',
ISNULL(vchFirstName,'') + ' ' + ISNULL(vchLastName,'') + ' ' +
CASE WHEN vchGoesBy IS NOT NULL THEN '(' + vchGoesBy + ')' ELSE ISNULL(vchGoesBy,'') END,
pn.iHHID
FROM CRM.dbo.cfn_PartyNameSearch(1, 'test') pn
WHERE pn.cPartyType = 'C'
)
x left join tableName v on v.id = x.id
and x.ObjType='ACCOUNT'
I want to sort by the pn.vchLastName for CONTACT. the other results sorting isn't a big deal honestly, and I am not able to edit the function that gives the results.
This general idea will work. You can work out the details
select 2 sortfield1
, whatever aliasName
from etc
union all
select 1 sortfield1
, yourFunctionResult aliasName
from etc
order by sortfield1, aliasName
Ordering takes place towards the end of the query execution, at least after all the data has been selected. Therefore you will have to order the entire result set at the end of the query. IIRC there is not conditonal ordering in T-SQL.

How to optimizing SQL Query with Cross Join

How can I make this SQL query more efficient? The CteFinal code shown below is a portion of my query which add up to 6 minutes to my query. The cteMonth is shown below. The cteDetail is another cte which pulls information directly from the database, and it takes less than a second to run.
What CteFinal is doing is creating missing fiscal period rows while including some of the column data from the row where f.FiscalPeriod=0.
I cannot add, delete, or change any of the indexes on the tables, as this is a ERP database and I'm not allowed to make those type of changes.
CteFinal:
SELECT Account,Month, CONVERT(DATETIME, CAST(#Year as varchar(4)) + '-' + CAST(Month as VARCHAR(2)) + '-' + '01', 102) JEDate
,accountdesc,'' Description,'' JournalCode,NULL JournalNum,NULL JournalLine
,'' LegalNumber,'' CurrencyCode,0.00 DebitAmount,0.00 CreditAmount,fiscalcalendarid,company,bookid,SegValue2,SegValue1,SegValue3,SegValue4
FROM cteDetail f
CROSS JOIN cteMonths m
WHERE f.FiscalPeriod=0 and not exists(select * from cteDetailADDCreatedZero x where x.Account=f.Account and x.FiscalPeriod=Month)
CteMonth:
cteMonths (Month) AS(
select 0 as Month
UNION select 1 as Month
UNION select 2 as Month
UNION select 3 as Month
UNION select 4 as Month
UNION select 5 as Month
UNION select 6 as Month
UNION select 7 as Month
UNION select 8 as Month
UNION select 9 as Month
UNION select 10 as Month
UNION select 11 as Month
UNION select 12 as Month)
Thank you!
Here's a slightly more efficient way to generate the 12 months of a given year (even more efficient if you have your own Numbers table):
DECLARE #year INT = 2013;
;WITH cteMonths([Month],AsDate) AS
(
SELECT n-1,DATEADD(YEAR, #Year-1900, DATEADD(MONTH,n-1,0)) FROM (
SELECT TOP (13) RANK() OVER (ORDER BY [object_id]) FROM sys.all_objects
) AS c(n)
)
SELECT [Month], AsDate FROM cteMonths;
So now, you can say:
;WITH cteMonths([Month],AsDate) AS
(
SELECT n,DATEADD(YEAR, #Year-1900, DATEADD(MONTH,n-1,0)) FROM (
SELECT TOP (13) RANK() OVER (ORDER BY [object_id]) FROM sys.all_objects
) AS c(n)
),
cteDetail AS
(
...no idea what is here...
),
cteDetailADDCreatedZero AS
(
...no idea what is here...
)
SELECT f.Account, m.[Month], JEDate = m.AsDate, f.accountdesc, Description = '',
JournalCode = '', JournalNum = NULL, JournalLine = NULL, LegalNumber = '',
CurrencyCode = '', DebitAmount = 0.00, CreditAmount = 0.00, f.fiscalcalendarid,
f.company, f.bookid, f.SegValue2, f.SegValue1, f.SegValue3, f.SegValue4
FROM cteMonths AS m
LEFT OUTER JOIN cteDetail AS f
ON ... some clause I am not clear on ...
WHERE f.FiscalPeriod = 0
AND NOT EXISTS
(
SELECT 1 FROM cteDetailADDCreatedZero AS x
WHERE x.Account = f.Account
AND x.FiscalPeriod = m.[Month]
);
I suspect this won't solve your problem though: it is likely that this is forcing an entire table scan on either whatever tables are mentioned in cteDetail or cteDetailADDCreatedZero or both. You should inspect the actual execution plan for this query and see if there are any scans or other expensive operations that could guide you towards better indexing. It also might just be that you have a bunch of inefficient CTEs stacked up together - we can't really help with that unless you show everything. CTEs are like views - if you start stacking them up on top of each other, you really limit the optimizer's ability to generate an efficient plan for you. At some point it will just throw its hands in the air...
One possibility is to physicalize the SQL View (if it the query is a view). Sometimes views with complex queries are slow.

Make a single column value from multiple rows column

I am facing a very isolated problem regarding to the dynamic sql query. I have two queries running on a single stored procedure. They are following
First query:
SELECT *
FROM (
SELECT ROW_NUMBER() OVER(ORDER BY viwPerformance.LastModifiedOn DESC) AS rowNumber,viwPerformance.* FROM viwPerformance WHERE OrgId=218 AND EmployeeId = 1668 AND IsTerminate = 0 AND TagId LIKE '%' + CAST(2893 AS VARCHAR) + '%' AND Archive='False' AND SmartGoalId IS NOT NULL
) AS E
WHERE rowNumber >= 1 AND
rowNumber < 11
it results all the column values and the SmartGoalId as
4471,2815,4751,4733,4863,4690,4691,4692,4693,4694
And the second query (here I need only SmartgoalId from the above query so I use stuff)
SELECT #strGoalIds = STUFF((SELECT ',' + CAST(SmartGoalId AS VARCHAR)
FROM (
SELECT ROW_NUMBER() OVER(ORDER BY viwPerformance.LastModifiedOn DESC) AS rowNumber,viwPerformance.* FROM viwPerformance WHERE OrgId=218 AND EmployeeId = 1668 AND IsTerminate = 0 AND TagId LIKE '%' + CAST(2893 AS VARCHAR) + '%' AND Archive='False' AND SmartGoalId IS NOT NULL
) AS E
WHERE rowNumber >= 1 AND
rowNumber < 11 FOR XML PATH('')), 1, 1, '')
and it's results the SmartgoalId as
4471,2815,4751,4733,4863,4651,4690,4691,4692,4693
Please note that the last id "4694" is not available from above query as the "4651"is added to it but it's not available from first query and this is correct that "4651" should not be in the second query result.
So my main point is why the second query gives different results as it's the same as the first query.
Note: Am I right that the Stuff function reversing the values and not giving them in correct order.
Because you have some rows with the same value for LastModifiedOn it depends how you want to handle ties.
If you want this query to always return the 10 most "recent" rows but always return the same ones when there are ties you can add another column to your ORDER BY viwPerformance.LastModifiedOn DESC clause that will make the sort unique and unchanging, like:
ORDER BY viwPerformance.LastModifiedOn,viwPerformance.SmartGoalId DESC)