Dynamically create categories for SQLite pivot/crosstab - sqlite

I realise it is possible to create a crosstab within sqlite, but is it possible to dynamically determine the relevant categories/columns at runtime rather than hardcoding them?
Given the following example, it can get rather tedious ...
SELECT
shop_id,
sum(CASE WHEN product = 'Fiesta' THEN units END) as Fiesta,
sum(CASE WHEN product = 'Focus' THEN units END) as Focus,
sum(CASE WHEN product = 'Puma' THEN units END) as Puma,
sum(units) AS total
FROM sales
GROUP BY shop_id
I managed to do this in SQLServer in a stored proceedure before and wondered if there was anything equivalent.

No, you can't do that in SQLite, since analytic means in SQLite lack many usefull features available in heavier RDBMSes. Here is the corresponding ticket, but it is in the pending status.

Old question, but anyway: I faked something like this in Ruby on Rails. For my purposes it works well.
def self.yearstats(attr)
# Determine number of columns
minyear = self.select("strftime('%Y', min(recorded_at)) AS minyear").first.minyear.to_i
maxyear = self.select("strftime('%Y', max(recorded_at)) AS maxyear").first.maxyear.to_i
# Stitch SQL query. Use explicit same column name to not confuse Rails' typecasting.
select_str = ["strftime('#{minyear}/%m/%d %H:%m', recorded_at) AS recorded_at"]
(minyear..maxyear).to_a.each do |y|
# avg because the table might have multiple rows per day
select_str += ["avg(case when strftime('%Y', recorded_at)='#{y}' then #{attr} end) AS value#{y}"]
end
self.select(select_str.join(",")).group("strftime('%m/%d', recorded_at)").all.collect {|row|
[row.recorded_at.utc.to_i*1000] + (minyear..maxyear).to_a.collect { |y| row.send("value#{y}") }
}
end
Note that for the first column I used a (fake) date using a fixed first year so that my graphing routines get a "real" date, not just day/month display. This is a little dirty but it works for my purposes. (Improvements still welcome...)
Instead of getting minyear and maxyear, you might want to do a SELECT DISTINCT.. to get the unique list of categories and modify the code appropriately.

Related

How do I limit query results, when distinct isn't distinct?

I have a bill of material file that I am trying to reduce to only the unique parts, and related data for the line. The problem I'm running into is multiple instances of a part number due to variations in the formatting or language in the part name from the system/s that a third party pulls the data from.
pn123 part_name
pn123 Part-name
pn123 Part name
pn123 German name
All other fields I select are equal, how do I limit this in the where clause to just one instance of the above for all different part numbers? Is there an equivalent to MAX() in a text string?
I am working around the issue in excel, by deleting the dupes.
select distinct
adhoc.ats_esh.Customs_Entry_Num
[VIN]as [Qlickview VIN]
,[Build_Date]
,[BOM_Level]
,[9802].[Supplier]
,[Part_number]
,[Part_Name] *******THIS IS THE PROBLEM FIELD*******
,[Unit_Price]
,[Usage]
,[Extended_Price]
from
adhoc.IMFM_9802_EU_AP [9802] inner join ADHOC.ATS_ESL
ON [9802].VIN = ADHOC.ATS_ESL.Part_Num
inner join adhoc.ATS_ESH
ON ADHOC.ATS_ESH.Trans_SK = ADHOC.ATS_ESL.Trans_SK
where
adhoc.ats_esh.importer ='ACME_CO'
and adhoc.ATS_ESH.ENTRY_SUMMARY_DATE >= '2/01/2018'
And adhoc.ATS_ESH.ENTRY_SUMMARY_DATE < '3/01/2018'
AND adhoc.ats_esl.Supplier in('supplier1','supplier2','supplier3')
--and adhoc.ats_esl.Part_Num like '%ABC%'
--and [BOM_Level] = '1' --**** use MAX()
The right way to do this is to have a table with part name and number where part number is a unique key. This way you join on Part_number and get a unique Part_name. You can also use Max(Part_name) if you use Group by Part_number but this will require you to rework your query a little bit.

Use case statement for parameter for column name in sql where clause

I have been looking all day for a solution that works for my situation. I have found some things that are very similar but don't work for my situation, I tried them.
Here is the scenario; I have two table base and partdetails. I have an asp website (internal ONLY) that has drop down lists to select the parameters for a SQL query that fills a data grid view.
My problem is this, I need to be able, based on the drop down list boxes on the page, assign the column name that the criteria that is entered to be searched for.
Here is the query that I am trying to define: (This one returns 0 rows)
sqlCmd.CommandText = ("Select ba.referenceid, ba.partnum, pd.width, pd.length, CONVERT(varchar(12), pd.dateentered, 101) As [dateentered], ba.partqty, ba.status, ba.material From tbl_dlbase ba Join tbl_partdetails pd On ba.referenceid = pd.referenceid Where Case #field1 When 'part #' Then 'ba.partnum' When 'Spacing' Then 'pd.spacing' When 'Surface' Then 'pd.surface' When 'Height' Then 'pd.height' When 'Thickness' Then 'pd.thickness' End Like '%' + #criteria1 + '%'")
sqlCmd.Parameters.AddWithValue("#field1", ddlSc1.SelectedItem.Text)
sqlCmd.Parameters.AddWithValue("#criteria1", txbCriteria1.Text)
This is the latest version of the SQL statement that I have tried. I need to be able to set the field/column name based on the selection from the drop down list ddlsc1 on the asp page.
I have also been trying the queries in Studio manager to see if maybe I have fat fingered something but it also returns 0 rows so I know something is wrong with the query.
So how can I set the column name field using a parameter for the name. I know this is a huge security concern with SQL injection but this is an internal only site, and more importantly my boss said he wants it done with variables.
I don't really see a problem with this other than you have single quotes around your THEN values. Does this fix it?
SELECT ba.referenceid
,ba.partnum
,pd.width
,pd.length
,CONVERT(VARCHAR(12), pd.dateentered, 101) AS [dateentered]
,ba.partqty
,ba.STATUS
,ba.material
FROM tbl_dlbase ba
JOIN tbl_partdetails pd ON ba.referenceid = pd.referenceid
WHERE CASE #field1
WHEN 'part #'
THEN ba.partnum
WHEN 'Spacing'
THEN pd.spacing
WHEN 'Surface'
THEN pd.surface
WHEN 'Height'
THEN pd.height
WHEN 'Thickness'
THEN pd.thickness
END LIKE '%' + #criteria1 + '%'

Merge Rows in Crystal Reports

I have a crystal report, which I already developed in below format.
My new requirement is to add two new columns to the report to show “Total Men”
Total Men column should merge into one, if the Date, Department and Vendor is same.
And it should show the Total Men which is = No of men Day shift + No of Men Night shift
You can create a Formula Field e.g. ShiftTotal and edit it to insert following code:
WhilePrintingRecords;
numberVar ShiftSum;
if {table_name.Date_Field} = Next({table_name.Date_Field})
and {table_name.Department_Field} = Next({table_name.Department_Field})
and {table_name.Vendor_Field} = Next({table_name.Vendor_Field}) then
ShiftSum := ShiftSum + {table_name.Men_Field} + Next({table_name.Men_Field})
else
ShiftSum := 0;
Place ShiftTotal in the Details section next to Men_Field
Format ShiftTotal to enable Suppress if Zero in Custom Style of Number tab
Sort your report by Date, Department and Vendor fields.
Above solution will work if there are maximum two records for same Date, Department and Vendor. Otherwise, it would be better to use Cross-Tab format, which (IMO) is better for such summaries.

MDX Compare DateTime attribute

I´m new to MDX and I have a simple question. I work with the TFS Cube it is named as Team System. My problem:
I have an IIF expression where I want to check additional my expression with an AND operator. There I want to compare two DateTime objects. The report should only show me the data from the actual date. Here my code:
IIF(ISEMPTY(SUM(YTD(
[Work Item].[PlannedWeek__HierarchyByWeek].CurrentMember),
[Measures].[EffectivelyValue]))
AND[Work Item].[PlannedWeek__HierarchyByWeek].CurrentMember < Now()
, [Measures].[EffectivelyValue]
, SUM(YTD(
[Work Item].[PlannedWeek__HierarchyByWeek].CurrentMember),
[Measures].[EffectivelyValue]) )
Planned Week is a self created field which has the DateTime datatype. The Now() function has also a DateTime datatype so the comparision should be right but it happens nothing.
Thanking you in anticipation
Eugen
Hierarchy members in MDX have a data type of 'member', and do not have a 'primitive' data type like datetime, string, or integer. Only member properties have 'primitive' data types. You could either define a property like datetime of your week attribute. Assuming you are SQL Server Analysis Services, this would be done via relationships.
Or you could use string operations to extract the date information from the UniqueName property which avoids having to change the cube. The UniqueName contains the data that you defined as the key in your cube design. Assuming your week hierarchy members have a key from which you can extract something like 20130820 for August 20, 3013 via string functions (I just will use Mid(, 30, 8) as an example below), you could do something like
CLng(Mid([Work Item].[PlannedWeek__HierarchyByWeek].CurrentMember.UniqueName, 30, 8))
<
CLng(Format(Now(), "yyyymmdd"))
You will have to check what exactly the CurrentMember.UniqueName shows in your cube to adapt the above code.
And finally, you could of course also use string methods to extract the relevant parts from the UniqueName and then the CDate function on that to compare to an unchanged Now(), i. e. do all operations on the left side of the <.
Hello thank you very much for you answer. I tried:
Mid([Work Item].[xxxx_PlannedWeek__HierarchyByWeek].CurrentMember.UniqueName,58,10)
shows e.g. 2013-07-21, 2013-07-28 (it shows the week endings)
so I tried this:
AND CLng(Mid([Work Item].[xxxx_PlannedWeek__HierarchyByWeek].CurrentMember.UniqueName,58,10))
<CLng(Format(Now(), "yyyy-mm-dd"))
But it happens nothing. If I execute it in a single way it shows everywhere "true". But I have datasets with dates which are e.g. > 2013-08-23. So there should be false values too.
EDIT: OK I solved the problem. The
Format(Now(), "yyyy-mm-dd")
must be
Format(Now(), "yyyy-MM-dd")

SELECT clause with a DATETIME column in Sybase 15

I'm trying to do a query like this on a table with a DATETIME column.
SELECT * FROM table WHERE the_date =
2011-03-06T15:53:34.890-05:00
I have the following as an string input from an external source:
2011-03-06T15:53:34.890-05:00
I need to perform a query on my database table and extract the row which contains this same date. In my database it gets stored as a DATETIME and looks like the following:
2011-03-06 15:53:34.89
I can probably manipulate the outside input slightly ( like strip off the -5:00 ). But I can't figure out how to do a simple select with the datetime column.
I found the convert function, and style 123 seems to match my needs but I can't get it to work. Here is the link to reference about style 123
http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.help.ase_15.0.blocks/html/blocks/blocks125.htm
I think that convert's slightly wrongly documented in that version of the docs.
Because this format always has century I think you only need use 23. Normally the 100 range for convert adds the century to the year format.
That format only goes down to seconds what's more.
If you want more you'll need to past together 2 x converts. That is, past a ymd part onto a convert(varchar, datetime-column, 14) and compare with your trimmed string. milliseconds comparison is likely to be a problem depending on where you got your big time string though because the Sybase binary stored form has a granularity of 300ms I think, so if your source string is from somewhere else it's not likely to compare. In other words - strip the milliseconds and compare as strings.
So maybe:
SELECT * FROM table WHERE convert(varchar,the_date,23) =
'2011-03-06T15:53:34'
But the convert on the column would prevent the use of an index, if that's a problem.
If you compare as datetimes then the convert is on the rhs - but you have to know what your milliseconds are in the_date. Then an index can be used.

Resources