Issues or bug with Snowflake pivot columns in double quotes - pivot-table

Are there any rules governing the use of mixed case column in Snowflake pivot tables? I have the following:
create or replace VIEW vw_tag_avg_by_qrtr_hour
as
SELECT t1.*
FROM (SELECT "Quarter Hour Time",
"Tag Description",
...
order by 1
I cannot replace "1" by "Quarter Hour Time". PowerBI chokes on this.
HOWEVER, if I use
FROM (SELECT "Quarter Hour Time" QRTR_HOUR_TIME,
both order by QRTR_HOUR_TIME and PowerBI are fine. This looks like a bug to me.

Related

trying to break down results of SQL query to show data for each month

I'm very new to SQL and have a problem I can't figure out.
I'm trying to replace an excel spreadsheet and turn it into a PowerBi report. Currently our team runs the following query to get the amount of active users every month and types it into an excel sheet which then graphs the number of users each month showing the increase. Since I don't want to manually input data each month my goal is to break down this query to give the current number of users in each month and add to that every month.
Desired result would look something like this
dateCreated # of Users
----------------------
2008-10 295
2008-11 355
2008-12 470
2009-01 522
I was able to break it down enough to give me the amount created each month, but that doesn't give me the total amount each month. This is the query that I used and a sample of the results I got.
SELECT
FORMAT(USERADDR.DateCreated, 'yyyy-MM') AS 'dateCreated',
COUNT(s.UserId) AS "# of Users"
FROM
ER.dbo.ssUser s,
ER.dbo.ssUserAddress USERADDR,
ER.dbo.ssAddress ADDRESS
WHERE
s.UserId = USERADDR.UserId
AND USERADDR.AddressId = ADDRESS.AddressId
AND Isdefault = 1
AND Type = 'soldto'
GROUP BY
FORMAT(USERADDR.DateCreated, 'yyyy-MM')
result sample:
dateCreated # of Users
2008-10 295
2008-11 41
2008-12 22
2009-01 19
This is almost there, but I need a running total. I've tried a lot of different things including SUM, SUM OVER, COUNT OVER etc. My boss suggested a while loop. I can't get that to work either and everything I've read says that should be the last resort. Here is one example of my failed attempts
SELECT
FORMAT(USERADDR.DateCreated, 'yyyy-MM') as 'dateCreated',
COUNT(s.UserId)
OVER(
PARTITION BY Month(USERADDR.DateCreated)
GROUP BY FORMAT(USERADDR.DateCreated, 'yyyy-MM')
)
AS "# of Users"
FROM
ER.dbo.User s,
ER.dbo.UserAddress USERADDR,
ER.dbo.Address ADDRESS
WHERE
s.UserId = USERADDR.UserId
AND USERADDR.AddressId = ADDRESS.AddressId
AND Isdefault = 1
AND Type = 'soldto'
--original query which gives total number of users right now.
SELECT
count(s.UserId) AS "# of Users"
FROM
ER.dbo.User s,
ER.dbo.UserAddress USERADDR,
ER.dbo.Address ADDRESS
WHERE
s.UserId = USERADDR.UserId
AND USERADDR.AddressId = ADDRESS.AddressId
AND Isdefault = 1
AND Type = 'soldto'
You can do a window sum() on the aggregated count of users per month, like so:
SELECT
FORMAT(USERADDR.DateCreated, 'yyyy-MM') [dateCreated],
SUM(COUNT(s.UserId)) OVER(ORDER BY FORMAT(USERADDR.DateCreated, 'yyyy-MM')) [# of Users]
FROM
ER.dbo.ssUser s
INNER JOIN ER.dbo.ssUserAddress USERADDR
ON s.UserId = USERADDR.UserId,
INNER JOIN ER.dbo.ssAddress ADDRESS
ON USERADDR.AddressId = ADDRESS.AddressId
WHERE Isdefault = 1 AND Type = 'soldto'
group by FORMAT(USERADDR.DateCreated, 'yyyy-MM')
Notes:
always prefer proper, explicit join syntax (with the ON keyword) over implicit, old-school joins, who were deprecated long time ago - I modified your query accordingly
SQLServer uses square brackets for identifiers - you should avoid single quotes, as they are generally used for litteral strings
you have unqualified column names in the WHERE clause: always qualify column names in your query, so it is easy to understand to which table they belong

SSRS: Why am I getting this aggregation?

I've recently uncovered that SSRS is doing a bizarre aggregation and I really don't understand why. In this report I'm building, as with other SQL queries I've built, I have a tendency to take preliminary results from an initial query, throw them into a temp table, and then perform another query and joining on that temp table to get my 'final' results I need to display. Here's an example:
--1. This query fetches all available rows based on the day (must be last day of month)
SELECT DISTINCT Salesperson ,c.Cust_Alias ,cost ,eomonth(CreateDate) createdate ,FaxNumber
INTO #equip
FROM PDICompany_2049_01.dbo.Customers c
JOIN PDICompany_2049_01.dbo.Customer_Locations cl ON c.Cust_Key = cl.CustLoc_Cust_Key
JOIN ricocustom..Equipment_OLD e ON e.FaxNumber = c.Cust_ID + '/' + cl.CustLoc_ID
JOIN PDICompany_2049_01.dbo.Charges ch ON ch.Chg_CustLoc_Key = cl.CustLoc_Key
WHERE Salesperson = #Salesperson
AND ch.Chg_Balance = 0
--2. This query fetches first result set, but filters further for matching date variable
SELECT DISTINCT (cost) EquipCost ,Salesperson ,DATEPART(YEAR, CreateDate) YEAR
,DATEPART(MONTH, CreateDate) MONTH ,Cust_Alias ,FaxNumber
INTO #equipcost
FROM #equip
WHERE Salesperson = #Salesperson
AND DATEPART(MONTH, CreateDate) = DATEPART(MONTH, #Start)
AND DATEPART(year, CreateDate) = DATEPART(year, #Start)
ORDER BY Cust_Alias
--3. Finally, getting sum of the EquipCost, with other KPI's, to put into my final result set
SELECT sum(EquipCost) EquipCost ,Salesperson ,YEAR ,MONTH ,Cust_Alias
INTO #temp_equipcost
FROM #equipcost
GROUP BY Salesperson ,year ,month ,Cust_Alias
Now I am aware that I could have easily reduced this to 2 queries instead of 3 in hindsight (and I have since gotten my results into a single query). But that's where I'm looking for the answer. In my GUI report, I had a row that was showing to have 180 for equipcost, but my query was showing 60. It wasn't until I altered my query to a single iteration (as opposed to the 3), and while I'm still getting the same result of 60, it now displays 60 in my GUI report.
I actually had this happen in another query as well, where I had 2 temp table result sets, but when I condensed it into one, my GUI report worked as expected.
Any ideas on why using multiple temp tables would affect my results via the GUI report in SQL Report Builder (NOT USING VB HERE!) but my SQL query within SSMS works as expected? And to be clear, only making the change described to the query and condensing it got my results, the GUI report in Report Builder is extremely basic, so nothing crazy regarding grouping, expressions, etc.
My best guess is that you accidentally had a situation where you did not properly clear the temp tables (or you populated the temp tables multiple times). As an alternative to temp tables, you could instead use table variables. Equally you could use a single query from the production tables -- using CTE if you want it to "feel" like 3 separate queries.

SQL Server 2014 Management Studio

I'm a non profit lawyer trying to set up a SQL Server database for my agency. The issue I'm having is query based: I need a simple query that will aggregate the total number of rows on a table, not the sum of the cell contents.
I working with 4 columns of I to: attorney's name, client name, trial date and remedy (the last 2 are date and dollar amount, so integers].
*** Script for SelectTopNRows command from SSMS***
SELECT TOP 100
[attorney]
,[client]
,[trial_date]
,[remedy]
FROM [MyLegalDB]
WHERE [trial_date] between '20160101' and '20160531'
I'm trying to find a way (script, batch file, etc) that will populate a total number of cases by month (according to trial date) total number of clients, and sum the remedy column.
Sorry for the vagueness. There are privilege rules in place. Hope that helps clarify.
Thanks
Assuming that your case history spans years, not just months, try this:
SELECT
,YEAR([trial_date]) AS [Year]
,MONTH([trial_date]) AS [Month]
,COUNT(1) AS [Trial_Count]
FROM [MyLegalDB]
WHERE [trial_date] between '20160101' and '20160531'
GROUP BY YEAR([trial_date]), MONTH([trial_date])
If you want to separate this by attorney, you would need to add that column to the SELECT list, as well as the GROUP BY clause, as such:
SELECT
[attorney]
,YEAR([trial_date]) AS [Year]
,MONTH([trial_date]) AS [Month]
,COUNT(1) AS [Trial_Count]
FROM [MyLegalDB]
WHERE [trial_date] between '20160101' and '20160531'
GROUP BY [attorney], YEAR([trial_date]), MONTH([trial_date])
This is a very general answer to a very general question. If you want me to be more specific, I'm going to have to understand your goal a little better. Hope it helps.

Query user logins using distinct and reprot back daily, weekly and monthly usage

I have a SQL Query, that I'm looking to report back site usage hourly, daily, weekly and monthly.
I require the query to use Distinct as the nature of the application will create several entries to the table upon a each new login to the site.
Here is what I have so far:
SELECT DISTINCT OPRID,
CONVERT(varchar(12), LOGINDTTM, 112) 'Date'
from PSACCESSLOG_HIST
where OPRID NOT IN ('AUTOPROC', 'PSAPPS', 'PHSADBA', 'PTWEBSERVER')
ORDER BY Date
This will give the following:
OPRID LOGIPADDRESS LOGINDTTM LOGOUTDTTM
dadams 10.1.1.5 20130612 20130612
jblake 10.1.1.5 20130614 20130614
First I do need to group the data as mentioned above by day. This is what I'm looking for, for this part:
LOGINDATE-TIME TOTAL-LOGINS
20130612 25
20130613 35
20130614 45
SELECT CONVERT(varchar(12), LOGINDTTM, 112) 'Date', count(*) as TOTAL-LOGINS
from PSACCESSLOG_HIST
where OPRID NOT IN ('AUTOPROC', 'PSAPPS', 'PHSADBA', 'PTWEBSERVER')
GROUP BY Date
ORDER BY Date
It is unclear to me how your query results in the table you produce. Your query does not mention logoutdttm. In any case, you can do what you want by grouping by date and counting the distinct "OPRID"s on each date (if I understand your request correctly):
SELECT CONVERT(varchar(12), LOGINDTTM, 112) as "Date", count(distinct OPRID) as NumOPRs
from PSACCESSLOG_HIST
where OPRID NOT IN ('AUTOPROC', 'PSAPPS', 'PHSADBA', 'PTWEBSERVER')
group by CONVERT(varchar(12), LOGINDTTM, 112)
ORDER BY Date
(As a side note, SQL Server doesn't allow you to use an alias in the group by column.)
Instead of the convert(), I prefer converting the date time to a date data type:
SELECT cast(LOGINDTTM as date) as "Date", count(distinct OPRID) as NumOPRs
from PSACCESSLOG_HIST
where OPRID NOT IN ('AUTOPROC', 'PSAPPS', 'PHSADBA', 'PTWEBSERVER')
group by cast(LOGINDTTM as date)
ORDER BY "Date"
Also, although SQL Server may allow you to put the aliases for columns in single quotes, you should use double quotes or square brackets. Single quotes have a strong meaning as a constant string in a SQL statement, and not as the name of a column or table.

Question about Crystal Reports + SQL Server stored procedure with GROUP BY

I'm writing a report in Crystal Reports XI Developer that runs a stored procedure in a SQL Server 2005 database. The record set returns a summary from log table grouped by Day and Hour.
Currently my query looks something like this:
SELECT
sum(colA) as "Total 1",
day(convert(smalldatetime, convert(float, Timestamp) / 1440 - 1)) as "Date",
datepart(hh, convert(smalldatetime, convert(float, Timestamp) / 1440 - 1)) as "Hour"
`etc...`
GROUP BY
Day, Hour
Ignore the date insanity, I think the system designers were drinking heavily when they worked out how to store their dates.
My problem is this: since there are not always records from each hour of the day, then I end up with gaps, which is understandable, but I'd like Crystal to be able to report on the entire 24 hours regardless of whether there is data or not.
I know I can change this by putting the entire query in a WHILE loop (within the stored procedure) and doing queries on the individual hours, but something inside me says that one query is better than 24.
I'd like to know if there's a way to have Crystal iterate through the hours of the day as opposed to iterating through the rows in the table as it normally does.
Alternatively, is there a way to format the query so that it includes the empty hour rows without killing my database server?
Here's how I solved this problem:
Create a local table in your SQL-Server. Call it "LU_Hours".
This table will have 1 integer field (called "Hours") with 24 rows. Of course, the values would be 1 through 24.
Right join this onto your existing query.
You might need to tweak this to make sure the nulls of empty hours are handled to your satisfaction.
You could use a WITH clause to create the 24 hours, then OUTER JOIN it.
WITH hours AS (
SELECT 1 AS hour
UNION
SELECT 2 AS hour
...
SELECT 24 AS hour
)
SELECT *
FROM hours h
LEFT OUTER JOIN [your table] x ON h.hour=x.datepart(hh, convert(smalldatetime, convert(float, Timestamp) / 1440 - 1))
This SQL would need to added to a Command.
Group as necessary in the SQL or the report.

Resources