I try to use SQLKata with SQL Server for the following use case:
Group turnover data per day/week/month/year for a configurable interval. As I also need to include the time units without any turnover data I chose to join this with a table valued function that returns a set of dates (see this link for more info about this SQL Server range of dates)
I query the table valued function in a CTE and would like to left join it with my turnover data. In order to do so I would need to use functions in the join condition though as the dates of the turnover data are more granular than the dates from the DateRange function.
As I have not seen an example in the SQL Kata documentation using a function in a join condition and trying it out gave an error too I guess it's not possible to do it like this.
What I tried:
Include a function in the join condition to reduce some details from the turnover date objects
Use 2 CTES like this: new Query().With(...).With(...) but it complained about the empty base query
What would be the best approach to implement this in a query?
Related
in Microsoft Access I need to bind a cross-tab query to a report. To bind the query I need to know the column names in advance which is the problem as I do not know which dates will be in the data. The date names end up as the columns in the cross-tab query. as the dates vary the column names vary and I can't bind the report as I don't know the column names. the best solution I can think of is to calculate a column that replaces the date with its order. then the column names will always be 1,2,3,4,5,6,7,8. However I haven't been able to create this calculated order column. No matter what I do access bugs out. Part of the cause is that This table will be used for a cross-tab query with parameters so access bugs out with any additional complications.
How do I turn StatusDate into CalculatedOrder?
Edit:
I cannot use a subquery to make CalculatedOrder as is sujested in the comments because the original query has parameters. access bugs out when a subquery draws on a query based on parameters.
The real problem was two bugs in Access. My guess is Access will bug at any additional complexity. if the original table has parameters work with a copy of the table that doesn't have parameters. In all cases, before calculating the crosstab, copy just your values into another temporary table. In Access, crosstab doesn't work if a crosstab column variable is a correlated subquery.
You can make the CalculatedOrder column using a correlated subquery similar to allenbrowne.com/ranking.html.
if the table has parameters:
PARAMETERS myfirstparameter
SELECT StatusDate, CrossTabRow, CrossTabValue INTO NoParametersTable
FROM MyTableWithParameters
WHERE ...
Then make a query with only a grouped StatusDate.
SELECT NoParametersTable.StatusDate
FROM NoParametersTable
GROUP BY NoParametersTable.StatusDate;
Then Turn StatusDate into Order using a correlatedsubquery:
SELECT CrossTabRow, CrossTabValue, (SELECT Count(dupe.StatusDate) +1 FROM [MyGroupedStatusDateQuery] as dupe WHERE dupe.StatusDate < [MyGroupedStatusDateQuery].StatusDate) AS [Order]
FROM NoParametersTable INNER JOIN [MyGroupedStatusDateQuery] ON NoParametersTable.StatusDate = MyGroupedStatusDateQuery.StatusDate)
finally make sure to turn this final query into a table without a correlatedsubquery by copying the values into another temporary table. run the crosstab on the final temporary table and the crosstab will work because the final table just has values instead of parameters and a correlated subquery.
Needs help in sql:
I need to group max online of each day by days
(http://prntscr.com/a7j2sm)
my sql select:
SELECT id, date, MAX(online)
FROM `record_online_1`
GROUP BY DAY(date)
and result - http://prntscr.com/a7j3sp
This is incorrect result because, max online is correct, but date and id of this top online is incorrect. I dont have ideas how solve this issue..
UPD: using MySQL MariaDB
When you perform an aggregate functions, you have to include items in the SELECT statement that aren't a part of an aggregate function in the GROUP BY clause. In T-SQL, you simply cannot execute the above query if you don't also GROUP BY "id" for example. However, some database systems allow you to forego this rule, but it's not smart enough to know which ID it should bring back to you. You should only be doing this if, for example, all "ids" for that segment are the same.
So what should you do? Do this in two steps. Step one, find the max values. You will lose the ID and DATETIME data.
SELECT DAY(date) AS Date, MAX(online) AS MaxOnline
FROM `record_online_1` GROUP BY DAY(date)
The above will get you a list of dates with the max for each day. INNER JOIN this to the original "record_online_1" table, joining specifically on the date and max value. You can use a CTE, temp table, subquery, etc to do this.
EDIT: I found an answer that is more eloquent than my own.
select MAX(InsertionDT),TaskStatus,tasksubstatus
from TransTasksFFMS_GVT
where TaskCode = 323155 group by TaskStatus,tasksubstatus
To use this query in the cube browser I have created a name query and used it as a dimension and it works, however I'm asked to do the calculation as a measure. Is it possible to translate this query to mdx to use it as the expression in a calculation?
What the query does: Returns the max insertion date for a each pair of status and sub status.
I'm new to MDX and to the whole cube idea!
Yes, first make the whole thing a star schema with a fact table/view and a dimension table for the tasks containing Task code, status, and substatus. Then define a measure for the InsertionDt using Max as the aggregation function.
I have a SQL statement that pulls data I need but I can't get the syntax right in Crystal Reports.
This statement works in SQL:
SELECT
max([meter_reading])
FROM [Forefront].[dbo].[EC_METER_HISTORY_MC]
WHERE [Meter_Number] = '1' AND [Transaction_Date] < '20130101'
GROUP BY
[Company_Code], [Equipment_Code], [Meter_Number]
This is what I changed it to in crystal but I can't get the right syntax.
SELECT
Maximum({EC_METER_HISTORY_MC.meter_reading})
FROM [EC_METER_HISTORY_MC]
WHERE {EC_METER_HISTORY_MC.Meter_Number} = '1'
AND {EC_METER_HISTORY_MC.Transaction_Date} < {1?Startdate}
GROUP BY {EC_METER_HISTORY_MC.Company_Code}
,{EC_METER_HISTORY_MC.Equipment_Code}
,{EC_METER_HISTORY_MC.Meter_Number}
Your first step should be reading up on how SQL Expressions work in Crystal. Here is a good link to get you started.
A few of your problems include:
Using a parameter field. SQL Expressions are not compatible with CR
parameters and cannot be used in them.
SQL Expressions can only return scalar values per row of your report. That means that your
use of GROUP BY doesn't serve any purpose.
Your use of curly braces means that you're referencing those fields in the main report query instead of in the subquery you're trying to create with this expression.
Here's a simplified example that would find the max meter reading of a particular meter (for Oracle since that's what I know and you didn't specify which DB you're using):
case when {EC_METER_HISTORY_MC.Meter_Number} is null then null
else (select max(Meter_Reading)
from EC_METER_HISTORY_MC
where Meter_Number={EC_METER_HISTORY_MC.Meter_Number} --filter by the meter number from main query
and Transaction_Date < Current_Date) --filter by some date. CAN'T use parameter here.
end
You can't use parameter fields in a SQL Expression, sadly. Perhaps you can correlate the Transaction_Date to a table in the main query. Otherwise, I would suggest using a Command.
You have two options for the Command:
Use a single Command object as the data source for the whole report--which involves (potentially) a fair amount of rework.
Add a Command to the existing table set (in the Database 'Expert'). Link it to other tables as desired. This will perform a second SELECT and join the results in memory (WhileReadingRecords, if I'm not mistaken). The slight performance hit may we worth the benefit.
Is it possible to join two tables based on the same date, not factoring in time?
Something like:
...FROM appointments LEFT JOIN sales ON
appointments.date = sales.date...
The only problem is it is a datetime field, so I want to make sure it is only looking at the date and ignoring time
You can do it like this:
FROM appointments
LEFT JOIN sales ON DATE(appointments.date) = DATE(sales.date)
But I'm pretty sure it won't be able to use an index, so will be very slow.
You might be better off adding a date column to each table.
the ON clause accepts an arbitrary conditional expression, so you can perform the date normalization in both sides before comparing, but it should represent a significant performance penalty.
Yes, but you have to join on a calculated expression, that strips the time from the datetime column values. This will make the query non-SARGable (It cannot use an index) so it will generate a table scan...
I don't know the syntax in mysql to strip time from a datetime value, but whatever it is, just write
FROM appointments a
LEFT JOIN sales s
ON StripTime(s.date) = StripTime(a.date)