sqlalchemy union multiple dynamic queries - sqlalchemy

I am dynamically creating raw text SQL queries as follows:
# my_items is a list of dicts.
# Each dict has keys, col_1 and col_2, with different values.
for col_values in my_items:
sql = sqlalchemy.text(
"SELECT col_1, col_2
FROM my_table WHERE col_1 = :col_1 AND col_2 = :col_2")
result = conn.execute(sql, **col_values)
However, the above is not efficient and I would like to retrieve all data once by unioning all queries:
queries = []
for col_values in my_items:
sql = sqlalchemy.text(
"SELECT col_1, col_2
FROM my_table WHERE col_1 = :col_1 AND col_2 = :col_2")
queries.append(sql)
final_sql = union(*queries) # does not work with Text objects
result = conn.execute(final_sql) # not sure how to bind params for individual items here!!
The problem is that, first, I cannot use union as it expects statements instead of text, and secondly, I do not know how to bind the respective input parameters to their queries.

You need to bind the parameters to the TextClause created with text and turn it into a TextualSelect.
queries = []
for col_values in my_items:
stmt = (
sqlalchemy.text(
"""
SELECT col_1, col_2
FROM my_table
WHERE col_1 = :col_1 AND col_2 = :col_2
"""
)
.bindparams(**col_values)
.columns(col_1=db.<TYPE>, col_2=db.<TYPE>)
)
queries.append(stmt)
final_stmt = union(*queries)
print(final_stmt.compile(compile_kwargs={"literal_binds": True}))
SELECT col_1, col_2
FROM my_table WHERE col_1 = 1 AND col_2 = 11
UNION ALL
SELECT col_1, col_2
FROM my_table WHERE col_1 = 3 AND col_2 = 13
UNION ALL
SELECT col_1, col_2
FROM my_table WHERE col_1 = 5 AND col_2 = 15
NB. I don't the actual data or schema, so I have not run this, let me know if there is any problem.

Related

Return somehting when no record exists, infobright db

I have a query like this and using infobright database --
select field1, field2
from foo
where filed1 in (1,2,3)
I want something to return even if there is no record in table. For example, there is record for filed1 = 2
and filed1 = 2 but nothing exists for filed1 = 3.
How could I make this query so I get something returning from the table for field1 = 3 ?
I could use ifnull in case there is a null value in the table for field1 = 3, but what I am trying find if there is absolutely nothing exists.
Although this is a short list of ID values you want, you can create a select/union to create the IDs, then left-join to the data table something like
select
AllIDs.ID,
foo.field1,
foo.field2
from
( select 1 ID union select 2 union select 3 ) as AllIDs
left join foo
on AllIDs.ID = foo.field1
If field1 is unique you can do this:
SELECT
ISNULL(MAX(field1), 'Default F1') as field1,
ISNULL(MAX(field2), 'Default F2') as field2
FROM foo
WHERE field1 in (1,2,3)
GROUP by field1
Otherwise you can use UNION like this:
SELECT field1, field2
FROM foo
WHERE filed1 in (1,2,3)
UNION
SELECT 'Default F1' as field1, 'Default F2' as field2
WHERE (SELECT COUNT(*) FROM foo WHERE filed1 in (1,2,3)) = 0

how to get row count in a table of different types in one table within same query

For Example,the table contains the column jobtype, the thing is we need to count no. of rows of same jobtype and at the same time for all the jobs in same query.
you can try this :
select jobtype, count(*) from your_table group by jobtype
union
select 'My Total', count(*) from your_table;
This will give result like(based on your table):
IT 5
Admin 10
Myv Total 15
You could create 2 int variables
$SQL = mysql_query('SELECT * FROM table');
$jobLookingFor = 'programmer';
$jobTypeSameCount = 0;
$jobTotalNumber = 0;
while($result = mysql_fetch_array($SQL))
{
if($result['jobtype'] === $jobLookingFor)
{
$jobTypeSameCount = $jobTypeSameCount + 1;
}
$jobTotalNumber = $jobTotalNumber + 1;
}
That is off the top of my head, so excuse the spelling mistakes.
after the while loop has completed
the jobTypeSameCount will be the number of the same jobs you are searching for
the jobTotalNumber will be the total rows including both the similar and other job type rows.
EDIT: Try this solution from a simillar question
SELECT COL_1, COL_2, COL_3, COL_4, COUNT(*)
FROM MyTable
GROUP BY COL_1, COL_2, COL_3, COL_4
If you ever want to weed out rows that don't have a duplicate:
SELECT COL_1, COL_2, COL_3, COL_4, COUNT()
FROM MyTable
GROUP BY COL_1, COL_2, COL_3, COL_4
HAVING COUNT() > 1
at: How to find duplicate count among several columns?
try this:
SELECT COUNT(*) AS same_duplicate_jobs ,job_type ,total_jobs = ( SELECT COUNT(*) FROM jobs) FROM jobs GROUP BY job_type HAVING COUNT(*) > 1

Deselecting a data with different column value

Hi guys I've got this table structure
field 1 field 2
---------------------------------------------
1 1
1 2
2 1
Then I want it to be like this when selecting Key Field2 = 1
field 1 field 2
---------------------------------------------
2 1
I don't want to return field1 = 1 because It contains different values field1 IN (1,2)
Thanks you so much.
Your post seems unclear because I think you mixed up column names in certain parts of your description. However, judging by your sample output, I'm going to assume you mean the following:
Select rows from the table where field2 contains identical values for the same field1.
If you only need to output field1 and field2, you could do the following:
SELECT field1, MAX(field2) AS field2
FROM atable
GROUP BY field1
HAVING COUNT(DISTINCT field2) = 1
You can omit DISTINCT if your table cannot hold duplicate pairs of (field1, field2).
However, if there are more columns in the table and some or all of them need to be returned too, you could first just get the field1 values like above, then join that row set back to atable to get complete rows, like this:
SELECT t.* /* or specify the necessary columns explicitly */
FROM atable AS t
INNER JOIN (
SELECT field1
FROM atable
GROUP BY field1
HAVING COUNT(DISTINCT field2) = 1
) s ON t.field1 = s.field1
Again, DISTINCT can be omitted, as explained above.
Since you are using SQL Server 2008, you could also use windowed aggregating. If your table doesn't contain duplicates of (field1, field2), you could use the following:
;
WITH counted AS (
SELECT
*,
cnt = COUNT(*) OVER (PARTITION BY field1)
FROM atable
)
SELECT
field1,
field2,
…
FROM counted
WHERE cnt = 1
But if the duplicates are allowed, you'll need to use a slightly different approach, because there's no windowing counterpart for COUNT(DISTINCT …). Here's what you could try:
;
WITH counted AS (
SELECT
*,
f2min = MIN(field2) OVER (PARTITION BY field1),
f2max = MAX(field2) OVER (PARTITION BY field1)
FROM atable
)
SELECT
field1,
field2,
…
FROM minmaxed
WHERE f2min = f2max
That is, you are getting the minimum and the maximum value of field2 for every field1 value. Then you are filtering out rows where f2min is not the same as f2max, because that would imply that there are different field2 values in the group.
SELECT * FROM table WHERE field_2 = 1 AND field_1 <> 1

Don't return any result if the precedent query has at least 1 result?

Basically I have this query:
( SELECT * FROM tbl WHERE type = 'word1' )
UNION
( SELECT * FROM tbl WHERE type = 'word2' ) // Run this query if there are no results with type = 1
Basically I would like to run the second query only if the first hasn't any results. is it possible?
The FIRST "PreCheck" query does a count of how many records ARE of type = 1. After that, if the count is greater than 1, then return 1, otherwise return 2.
Now, THAT answer can be used in the join (which is always a single row via COUNT(*)) which will either have a 1 or 2 value. THAT value will be the second value is the EQUALITY conditon. So, if there IS an entry of 1, the result will be as if
WHERE t1.Type = 1
Thus never allowing any 2 in the test. HOWEVER, if NO entries are found, it will have a value of 2 and thus create a WHERE clause of
WHERE t1.type = 2
select t1.*
from
( select if( count(*) > 0, 1, 2 ) IncludeType
from tbl t2
where t2.type = 1 ) preCheck,
tbl t1
where
t1.type = preCheck.IncludeType
If there is an index on the "type" column, the first query should be almost instantaneous.
You could write
select * from tbl
where type = 1
union
select * from tbl
where type = 2
and not exists( select * from tble where type = 1 )
but this probably won't perform as well as just doing it in your program
It does the trick:
SELECT tbl.* FROM tbl JOIN (SELECT min(type) min_type FROM tbl WHERE type between 1 and 2 ) on min_type = type
First, it selects the lesser of these two types, if any exists, and then oins this one number table to your table. It is actually a simple filter. You can use WHERE instead of JOIN, if you want.
SELECT tbl.* FROM tbl WHERE (SELECT min(type) FROM tbl WHERE type between 1 and 2 ) = type

EF. How to union tables, sort rows, and get top entities?

I want to union records from 2 tables, sort them, and read TOP rows from result set.
T1
--------
Id, Timestamp, Text1
T2
--------
Id, Timestamp, Text2
With SQL it can be done this way:
SELECT TOP 10 * FROM
(
SELECT
[Timestamp],
[Text1]
FROM
T1
UNION
SELECT
[Timestamp],
[Text2]
FROM
T2
) as x
ORDER BY [Timestamp]
Q: How can I do that task using EF linq?
You need an anonymous type with the same property names and types before you can do an Union operation:
var t1List = from a in allT1
select new
{
TimeStamp = a.TimeStamp,
Text = a.Text1
};
var t2List = from b in allT2
select new
{
TimeStamp = b.TimeStamp,
Text = b.Text2
};
var result = t1List.Union(t2List).OrderBy(ab => ab.TimeStamp).Take(10);
How about something like:
var top10 = EFentity.t2.Union(EFentity.t1.ToList()).OrderBy(t=>t.Timestamp).ToList().Take(10);