Simple.Data query by multiple values - WHERE IN () - simple.data

Using Simple.Data how can I pass multiple values to a query?
Example generated SQL:
SELECT a,b,c
FROM GreatTable
WHERE x in (1,2,3)
Join support would be nice, too.
Does Simple.Data allow this sort of thing?

If you have no gaps in your values e.g. 1,2,3,4 then use:-
var list = db.GreatTable.FindAllByX(1.to(4));
this produces a where x BETWEEN 1 AND 4
Otherwise if you have gaps in your range, e.g. 1,2,4,6 then use an integer array:-
var list = db.GreatTable.FindAllByX(new[] { 1, 2, 4, 6 });
this produces a where x IN (1,2,4,6)

Related

MariaDB select record for every find_in_set values

I'm pretty sure there are already topics on this subject. I just can't find them. Sorry...
I want to select rows from a table where column = 1 or 2, or 3, or 3.
I need to use FIND_IN_SET because I don't know those numbers.
What I have now is (the numbers are an example):
SELECT
*
FROM
my_table
WHERE
FIND_IN_SET(my_column, '1,2,3,3')
The query, sure, returns 3 rows.
I need 4, cause I have 4 numbers...

Split column value in sqlite

Am new to sqlite in my learning I come across the subString function so in my exercise, My table name is t1 and my column value is Partha000099 I want to increment by 1 eg., Partha000100 when i try with
SELECT SUBSTR(MAX(ID),6) FROM t1
am getting output as 000099 when I increment by 1 with the below query
SELECT SUBSTR(MAX(ID),6)+1 FROM t1
am getting output as 100, Now my question is how to construct it back as I expect
I tried with the below query,
SELECT 'Partha' || SUBSTR(MAX(ID),6)+1 FROM t1
am getting output as 1. Please some one help me.
While my solution will work, I would advice you against this type of key generation. "SELECT MAX(ID)+1" to generate the next key will be fraught with problems in more concurrent databases and you risk generating duplicate keys in a busy application/system.
It would be better to split the key into two columns, one with the group or name 'Partha', and the other column with an automatically incremented number.
However, having said that, here's how to generate the next key like your example.
You need to:
Split the key into two
Increment the numeric part
Convert it back to a string
Pad it to 6 digits
Here's the SQL that will do that:
SELECT SUBSTR(ID, 1, 6) || SUBSTR('000000' || (SUBSTR(MAX(ID), 7)+1), -6) FROM t1;
To pad it to 6 digits, I prepend 6 zeroes, then grab the last 6 digits from the resulting string with this type of expression
SUBSTR(x, -6)
The reason why you got 1 was that your expression was grouped like this:
SELECT .... + 1
And the .... part, your string concatenation, was then attempted converted to a number, which resulted in 0, thus 0+1 gives 1.
To get the unpadded result you could've just added some parenthesis:
SELECT 'Partha' || (SUBSTR(MAX(ID),6)+1) FROM t1
^ ^
This, however, would also be wrong as it would return Partha1, and that is because SUBSTR(..., 6) grabs the 6th character and onwards and the 6th character is the final a in Partha, so to get Partha100 you would need this:
SELECT 'Partha' || (SUBSTR(MAX(ID),7)+1) FROM t1
^

SQL Query to transpose rows into columns

I have a .net web application that uses SQL Server 2008. The data table I am trying to display in a grid contains columns that are actually rows of another table. Right now, I am doing this in the BLL, reading data into data table; getting the data from another table and making it into columns of first data table and then going through each row of data in that data table to populate the new columns. Very time consuming and slow.
I believe this can be done through a query in SQL 2012 and above using "Transpose" or something similar but not sure if it is possible in 2008. I researched and tried using "pivot" but I am not good at SQL and couldn't get it to work.
This is a simplified example of DB tables and what I need to display:
Facility Table:
FacilityID
12345
67890
PartnerInfo table:
PartnerID Partner
1 Partner1
2 Partner2
3 Partner3
FacilityPartner table:
FacilityID PartnerID
12345 1
12345 3
67890 2
67890 3
Need a query to return something like:
FacilityID Partner1 Partner2 Partner3
12345 true false true
67890 false true true
Following should give some idea on pivoting the data. It doesn't give you exact true false as you asked.
declare #facility table (facilityId int)
declare #PartnerInfo table (partnerid int, partnerN varchar(1000))
declare #FacilityPartner table (facilityId int,partnerid int)
insert into #facility values (12345)
insert into #facility values (67890)
insert into #facility values (67891)
insert into #PartnerInfo values (1, 'partner1')
insert into #PartnerInfo values (2, 'partner2')
insert into #PartnerInfo values (3, 'partner3')
insert into #FacilityPartner values(12345, 1)
insert into #FacilityPartner values(12345, 3)
insert into #FacilityPartner values(67890, 2)
insert into #FacilityPartner values(67890, 3)
select f.facilityId as facid, p.PartnerN as partn, 100 as val
FROM #facility f
LEFT join #FacilityPartner fp on f.facilityId = fp.facilityId
LEFT JOIN #PartnerInfo p on p.partnerid = fp.partnerid
select facid, Partner1 , partner2,partner3 FROM
(select f.facilityId as facid, p.PartnerN as partn, 100 as val
FROM #facility f
LEFT join #FacilityPartner fp on f.facilityId = fp.facilityId
LEFT JOIN #PartnerInfo p on p.partnerid = fp.partnerid) x
PIVOT(
avg(val)
for partn in ([partner1], [partner2],[partner3])
) as pvt
The first thing to understand is, just like many other languages, SQL has a sort of "compile" process, where an execution plan is produced. An SQL query MUST be able to know the precise number and types of columns at compile time, without referencing the data (it does have some table metadata available for the compile, which is why SELECT * works).
This means what you want to do is only possible if one of two conditions is met:
You must know the precise number of partners (and the names for the columns, in this case) ahead of time. This is true even for a query using the PIVOT keyword.
You must be willing to do this in multiple steps, using dynamic SQL, where the first step looks at the data to know how many columns you'll need. Then you can build up a new query in a varchar variable, and finally execute that string using Exec() orsp_executesql(). This works because the last step invokes a new "compile" process and execution context for that string variable.
Of course there's also a third option: pivot the data in your client code. That is my preference. Most people, though, opt for option 2.

SQLite returning data in custom order

I'm using an SQLite query (in an iOS application) as follows:
SELECT * FROM tblStations WHERE StationID IN ('206','114','113','111','112','213','214','215','602','603','604')
However, I'm getting the resulting data in either descending or ascending order, when what I really want is for the data to be returned in the order I've specified in the IN clause.
Is this possible?
A trivial way to sort the results
NSArray *stationIDs = #[#206,#114,#113,#111,#112,#213,#214,#215,#602,#603,#604];
NSArray *stations = #[#{#"Id":#(604)},#{#"Id":#(603)},#{#"Id":#(602)},#{#"Id":#(215)},
#{#"Id":#(214)},#{#"Id":#(213)},#{#"Id":#(112)},#{#"Id":#(111)},
#{#"Id":#(113)},#{#"Id":#(114)},#{#"Id":#(206)}];
stations = [stations sortedArrayUsingComparator:
^NSComparisonResult(NSDictionary * dict1, NSDictionary *dict2)
{
NSUInteger index1 = [stationIDs indexOfObject:dict1[#"Id"]];
NSUInteger index2 = [stationIDs indexOfObject:dict2[#"Id"]];
return [#(index1) compare:#(index2)];
}];
You could use a CASE expression to map these station IDs to another value that is suitable for sorting:
SELECT *
FROM tblStations
WHERE StationID IN ('206','114','113','111','112',
'213','214','215','602','603','604')
ORDER BY CASE StationID
WHEN '206' THEN 1
WHEN '114' THEN 2
WHEN '113' THEN 3
WHEN '111' THEN 4
WHEN '112' THEN 5
WHEN '213' THEN 6
WHEN '214' THEN 7
WHEN '215' THEN 8
WHEN '602' THEN 9
WHEN '603' THEN 10
WHEN '604' THEN 11
END
I don't believe there's any means of returning SQL data in an order that isn't ascending, descending or random (either intentionally so, or simply in the order the database engine chooses to return the data).
As such, it would probably make sense to simply fetch all of the data returned by the SQLite query and store it in an NSDictionary keyed on the StationID value. It would then be trivial to retrieve in the order you require.
add an additional column to use for sorting. e.g. add a column named "sortMePlease". Fill this column according to your needs, meaning for the row for stationID 216 enter 1, for 114 enter 2, .... and finally add "ORDER BY sortMePlease ASC" to your query.
A second way of doing it (the first one being with CASE WHEN ... THEN END as already stated in another answer) is:
ORDER BY StationID=206 DESC,
StationID=114 DESC,
StationID=113 DESC,
StationID=111 DESC,
StationID=112 DESC,
StationID=213 DESC,
etc.

Group by ranges in SQLite

I have a SQLite table which contains a numeric field field_name. I need to group by ranges of this column, something like this: SELECT CAST(field_name/100 AS INT), COUNT(*) FROM table GROUP BY CAST(field_name/100 AS INT), but including ranges which have no value (COUNT for them should be 0). And I can't get how to perform such a query?
You can do this by using a join and (though kludgy) an extra table.
The extra table would contain each of the values you want a row for in the response to your query (this would not only fill in missing CAST(field_name/100 AS INT) values between your returned values, but also let you expand it such that if your current groups were 5, 6, 7 you could include 0 through 10.
In other flavors of SQL you'd be able to right join or full outer join, and you'd be on your way. Alas, SQLite doesn't offer these.
Accordingly, we'll use a cross join (join everything to everything) and then filter. If you've got a relatively small database or a small number of groups, you're in good shape. If you have large numbers of both, this will be a very intensive way to go about this (the cross join result will have #ofRowsOfData * #ofGroups rows, so watch out).
Example:
TABLE: groups_for_report
desired_group
-------------
0
1
2
3
4
5
6
Table: data
fieldname other_field
--------- -----------
250 somestuff
230 someotherstuff
600 stuff
you would use a query like
select groups_for_report.desired_group, count(data.fieldname)
from data
cross join groups_for_report
where CAST(fieldname/100.0 AS INT)=desired_group
group by desired_group;

Resources