variable column names in sql table valued function - sql

Suppose that I am using a sql server to keep track of all my personal expenses and that I am tagging everything with a date and a category.
This allows me to do things like aggregate monthly expenses per category and look at the last several months of expenses with each category as a row and the most recent months as columns.
What I am stuck on is the fact that I am having to name the columns things like "most recent month", "previous month", and "2 months ago". I would really prefer to be able to name them something like "Jan10", "Feb10", or "Mar09" or something like that and have them update automatically every month.
Calculating the names is simple enough, but I'm not sure how to get sql server to interpret a formula or join or anything like that as the alias for a column.
Any insights on this one?

What I am stuck on is the fact that I am having to name the columns things like "most recent month", "previous month", and "2 months ago". I would really prefer to be able to name them something like "Jan10", "Feb10", or "Mar09" or something like that and have them update automatically every month.
That approach means creating multiple columns, which will eventually hit the limit. In SQL Server, that's 1,024 for a non-wide and 30,000 for a wide table ...
A better approach is to store the date, and section/partition the data in the query as needed. Because Jan 10th is going to have a different value for 2009, 2010, 2011, etc...

It looks to me like you're trying to store data the same way you want to view it. That is not a very good way of going about it. I would suggest the following:
Your table should have the essentials, say:
Store (This could become its own table, but we can leave it as a string)
Category
Amount Spent
Date
Then, once you have this data, you can report on it. This report will do the heavy lifting, and will be dynamic in the sense that you don't need to hardcode values. The following is just an example, and I can't promise the syntax is even correct.
SELECT Store, SUM(CASE WHEN Date > GETDATE() - 14 THEN AmountSpent ELSE 0 END)
FROM YourTable
GROUP BY Store
The above will give you all money spent at each store in the last 14 days. This window will be "sliding", every time you run it, it will look back two weeks; no hardcoding.

You may wish to acquaint with Entity-attribute-value model and approaches.

Related

Replacing incorrectly entered dates in sql server

I have ran a query is SQL server. there is a name category and every category has a date that it started... however sometimes data was incorrectly entered in the front end so when I do the data pull it returns two start dates per category when in reality just the earliest date should be present. is there any sql code I can throw into this join query that replaces all situations when a category has two dates with the earliest one?
From what I understand, you need to use the MIN() function to get only the earliest entered event when querying your table. You can achieve this my using something similar to the following:
SELECT
categoryName,
MIN(categoryDate)
FROM Category
GROUP BY categoryName
However, I am not sure this is what you need since we have no dataset to verify against. Ideally, you can explain in a more clear way, what you need to achieve, and we can help you better.

Add column of customer's past purchase total at time of current purchase and find rate of purchases that are from a returning customer - SQL

I am working with a table containing the purchase history for a shop. There is a purchase id, a date column and a customer id. I am trying (without much success so far) to do two things:
Add a column which for each purchase tells how many purchases the customer made before this (in the last month). I started by joining the table on itself but haven't got much further. I know I'll need to somehow filter the date so it only counts purchases before this date and not more than a month ago. Any suggestions on a simple way to tackle this?
The second thing I would like to see is what the weekly rate of returning customer transactions is. That is, what proportion of the purchases are by someone who purchased recently (in the last month). Ideally I would be able to graph this so from my sql queries I would like to end up with a date, weekly total (the 7 days up to the date) and weekly rate. I have been reading up on rolling windows and to be honest am having a bit of trouble getting my head around it. My SQL level is still quite low unfortunately. Any tips on a relatively simple way to do this would be much appreciated.
Thanks
I would need to see your data structure for the table(s) to better answer your question. But right off the top of my head is seems like you just need a simple SELECT COUNT.
So something like this would return all transactions from a single customer made in the past month:
SELECT COUNT(purchase_id)
FROM purchases
WHERE customer_id='some_customer_id'
AND date >= DATEADD(m, -1, GETDATE());
As for your second question you would probably want to setup a job (jenkins, ect..) that would run a query every month. The results of which you would plot. Checkout https://oss.oetiker.ch/rrdtool/ for graphing

DAX sum different DateTime

I have a problem here, i would like to sum the work time from my employee based on the data (time2 - time 1) daily and here is my query:
Effective Minute Work Time = 24. * 60 * (LASTNONBLANK(time2,0) -FIRSTNONBLANK(time1,0))
It works daily, but if i drill up to weekly / monthly data it show the wrong sum as it shown below :
What i want is summary of minute between daily different times (time2-time1)
Thanks for your help :)
You have several approaches you can take: the hard way or the easier way :). The harder (at least for me :)) is to use DAX to do this. You would:
1) create a date table,
2) Use the DAX calculate function to evaluate your last non-blank and first non-blank values (you might need to use calculate table, but I'm not sure; DAX experts jump in). Then subtract one vs. the other.
This will give you correct values for a given day for a given person. You can enforce the latter condition by putting a 'has one value' guard on the person name so that your measure informs the report author if they're not using it right.
Doing the same for dates is a little trickier. In the example you show you are including the date in the row grouping. But if you change your mind and want instead to have 'total hours worked by person' or 'total hours worked by everyone' you're not done with modelling yet.
Your next step is to use calculate table in combination with calculate to create a measure that returns the total. You'll use calculate table so you evaluate each date and the hours worked on that date by person. Then you'll use calculate to summarize that all down to a single number. If you're not careful with your DAX (or report authoring) you might mix which person you're summarizing for so that your first/last non blank are not at the person level. It gets intense quickly.
Your easier solution, though it might be more limited in its application - depends really on your scenario - is to use the query to transform the data into a summary by day and person using the group by command. This will give you a row per person per day with their start and end times. Then you can quickly calculate the hours worked on that day. Then you can quite easily build visuals on top of the summary data. Of course you give up some of the flexibility of the having a proper data model. However if you have a date table, a person table, and your summary table and then setup your relationships correctly you can achieve answers to the most common questions.

Standing Orders with SQL / HQL

I implemented an own program to manage my incomes and expenses some years ago. However, I realized that I need some kind of "standing orders" - incomes or expenses which repeat monthly, quarterly or yearly. I would add them in an own table (with the value, description, start and end date, repetition rate, ...). But how do I query them with SQL/HQL in a smart way? For example: I want all incomes for a given month. Now I have to run through all entries and check somehow whether the start date plus a multiple of the repetition rate "hits" the current month. Seems to me very cumbersome. Is there an easy way to implement such operations?
Sorry for answering my own question, but in the meantime I think that it is not that difficult. Even when using HQL it is possible to calculate the number of months between two dates (if not with an existing function, it can still be done in the HQL expression using an obvious formula). Of course one has to handle the case correctly with days which exist in one month but not in the other (e.g., february), but this is a detail which can likely be ignored in my case.
Knowing the number of months between the current month, a simple modulo expression can check whether the current month is "hit" by the standing order. The rest is simple.

TSQL Paramterised Pivot Query SP SSRS

Wonder if anyone has done this before and what solution you came up with?
I have a Stored Proc that basically is a financial aged debtors query. I have added params to it so that you can select the Start Date, Frequency and Period length of the query. e.g. I could pick 12 months back from TODAY or 01/01/2012 or 4 Quarters back or 1 year back depending on the detail of the output I wish to see.
All well and good and when I run it in SQL it is lovely and works beautifully. I have pivoted the data within the SP in different ways depending on the Period param so that the columns show correctly (i.e. Shows the month name column for months, Quarter name for quarters etc etc.) so the pivot is conditional on the input parameter.
As I say in SQL it is a beautiful thing... now how the hell do I display it in SSRS!? :o)
As the PIVOT is conditional I can't see the available fields and I've got to a point where I can't think anymore of a way around it.
Any help appreciated!
Assuming I got you right, there is an option to place the entire SP in the Dataset.
In the dataset properties , change the query type to Store Procedure.
Hope it helps for you...