MYSQL Select tableX from all databases - mysqli-multi-query

Let's say I have 50 databases that all have same schema and all have table 'plays'.
Is there any possible way to SELECT all the data from table 'plays' from all the databases at once ?
Is there any way to do this if I dont know how many databases I have ?
Currently I would do this :
(SELECT * FROM db1.plays WHERE condition)
UNION
(SELECT * FROM db2.plays WHERE condition)
UNION...
(SELECT * FROM db50.plays WHERE condition)
Is there any way to write less code for this ?
Regards

I'm not sure, but to shorten your code, you could do
Select * FROM db1.plays, db2.plays, ...., db3.plays WHERE <condition>
Another thing that comes to mind is using the table INFORMATION_SCHEMA. Maybe someone else has a better idea.

Related

Activerecord or Raw SQL

I have some RAW sql and I'm not sure if it would be better as an Activerecord call or should I use RAW sql. Would this be easy to convert to AR?
select *
from logs t1
where
log_status_id = 2 and log_type_id = 1
and not exists
(
select *
from logs t2
where t2.log_version_id = t1.log_version_id
and t2.log_status_id in (1,3,4)
and log_type_id = 1
)
ORDER BY created_at ASC
So something like this?:
Log.where(:log_status_id=>2, log_type_id => 1).where.not(Log.where.....)
You could do this using AREL. See Rails 3: Arel for NOT EXISTS? for an example.
Personally I often find raw SQL to be more readable/maintainable than AREL queries, though. And I guess most developers are more familiar with it in general, too.
But in any case, your approach to separate the narrowing by log_states_id and log_type_id from the subquery is a good idea. Even if your .where.not construct won't work as written.
This should do the trick however:
Log.where(log_status_id: 2, log_type_id: 1)
.where("NOT EXISTS (
select *
from logs t2
where t2.log_version_id = logs.log_version_id
and t2.log_status_id in (1,3,4)
and t2.log_type_id = logs.log_type_id)")
.order(:created_at)
The only constellation where this might become problematic is when you try to join this query to other queries because the outer table will likely receive a different alias than logs.

SQL Multiple Joins on same table with where clause

Folks,
I've had a pretty thorough search before posting and couldn't see this answered anywhere previously. Perhaps it isn't possible.... I'm using SQL server 2008 R2
Anyway, thanks in advance for looking/helping.
I have two tables that I'd like to join.
Table1 (t1):
Account------Name--------Amount
12345-------account1-----10000.00
12346-------account2-----20000.00
Table2 (t2):
ID-----Account---extraData
10-----12345-----ZZ100
20-----12345-----ZZ250
30-----12345-----ZZ400
10-----12346-----ZZ150
20-----12346-----ZZ200
I'm trying to return the following from the above tables:
t1.Account---t1.Name------ID1(t2.ID=10)---ID2(td.ID=20)----SUM(Amount)
12345--------account1-------ZZ100------------ZZ250-------------10000.00
12346--------account2-------ZZ150------------ZZ200-------------20000.00
I have tried various joins of sorts and a union, but can't seem to get the results above. Most result in either nothing, or the Amount column returning as double the required result.
My starting point is:
Select t1.Account, t1.Name, t2A.extraData, t2B.extraData, SUM(t1.AMOUNT)
from table1 t1
join table2 t2A on t1.Account = t2A.Account and t2A.ID = '10'
join table2 t2B on t1.Account = t2B.Account and t2B.ID = '20'
Group by t1.Account, t1.Name, t2A.extraData, t2B.extraData
I've reduced the code and complexity of the query for this thread, but the problem is as above. I have no control over the table structure as they form part of an accounting system that I can't amend (I could, but I'd upset one or two people!).
Hopefully I've explained the issue clearly enough. It seems like it should be simple, but I can't seem to fathom it - perhaps I've just been staring too long. Anyway, thanks in advance for your assistance.
Edit: to change the code to reflect the first response highlighting a mistake in my posting.
Please try this. I think this helps you to achieve your result.
DECLARE #ids varchar(max)
SELECT #ids=STUFF((SELECT DISTINCT ', [' + CAST(ID AS VARCHAR(10))+']'
FROM t2
FOR XML PATH(''), TYPE)
.value('.','NVARCHAR(MAX)'),1,2,' ')
SELECT #ids
EXECUTE ('SELECT
Account,Name,'+#ids+',Amount
FROM
(SELECT t1.Account,Name,ID,ExtraData,SUM(Amount) AS Amount
FROM t1 t1 INNER JOIN t2 t2 ON t1.Account=t2.Account
GROUP BY t1.Account,Name,ID,ExtraData) AS SourceTable
PIVOT
(
MAX(ExtraData)
FOR ID IN ('+#ids+')
) AS PivotTable;')

Using distinct in a join

I'm still a novice at SQL and I need to run a report which JOINs 3 tables. The third table has duplicates of fields I need. So I tried to join with a distinct option but hat didn't work. Can anyone suggest the right code I could use?
My Code looks like this:
SELECT
C.CUSTOMER_CODE
, MS.SALESMAN_NAME
, SUM(C.REVENUE_AMT)
FROM C_REVENUE_ANALYSIS C
JOIN M_CUSTOMER MC ON C.CUSTOMER_CODE = MC.CUSTOMER_CODE
/* This following JOIN is the issue. */
JOIN M_SALESMAN MS ON MC.SALESMAN_CODE = (SELECT SALESMAN_CODE FROM M_SALESMAN WHERE COMP_CODE = '00')
WHERE REVENUE_DATE >= :from_date
AND REVENUE_DATE <= :to_date
GROUP BY C.CUSTOMER_CODE, MS.SALESMAN_NAME
I also tried a different variation to get a DISTINCT.
/* I also tried this variation to get a distinct */
JOIN M_SALESMAN MS ON MC.SALESMAN_CODE =
(SELECT distinct(SALESMAN_CODE) FROM M_SALESMAN)
Please can anyone help? I would truly appreciate it.
Thanks in advance.
select distinct
c.customer_code,
ms.salesman_code,
SUM(c.revenue_amt)
FROM
c_revenue c,
m_customer mc,
m_salesman ms
where
c.customer_code = mc.customer_code
AND mc.salesman_code = ms.salesman_code
AND ms.comp_code = '00'
AND Revenue_Date BETWEEN (from_date AND to_date)
group by
c.customer_code, ms.salesman_name
The above will return you any distinct combination of Customer Code, Salesman Code and SUM of Revenue Amount where the c.CustomerCode matches an mc.customer_code AND that same mc record matches an ms.salesman_code AND that ms record has a comp_code of '00' AND the Revenue_Date is between the from and to variables. Then, the whole result will be grouped by customer code and salesman name; the only thing that will cause duplicates to appear is if the SUM(revenue) is somehow different.
To explain, if you're just doing a straight JOIN, you don't need the JOIN keywords. I find it tends to convolute things; you only need them if you're doing an "odd" join, like an LEFT/RIGHT join. I don't know your data model so the above MIGHT still return duplicates but, if so, let me know.

How do I decrease sql query execution time in my rails app?

I have query as
select i.shipping_charges, i.shipping_carrier, i.shipping_method,
i.tracking_number, i.origin_zip_code, i.origin_city,
i.origin_country, i.weight_value, i.weight_unit,
i.delivery_date, i.shipping_date, i.shipping_description,
i.delivery_zip_code, i.delivery_street_add, i.item_id,
i.start_at, i.end_at, i.id
from (items it
left join item_shipping_details i on it.id = i.item_id)
left join users u on u.id = it.alert_user_id
where it.user_id=4 AND i.id in (35,602,1175,1176,1177,604,1178,1174,
1165,1179,930,1160,917,914,925,909,920,1147,910)
AND (it.alert_user_id is null OR u.user_type in (2,3))
AND (it.outbound != true OR it.outbound is null)
It takes 8ms in postgresql to run.
Please tell any other alternative solution to this?
A couple of things were odd or straight out nonsensical about your query.
Primary table in the FROM list was items, but you don't have a single column of it in the SELECT list main table. The way you had it, it would at best add a bunch of rows with only NULL values, while confusing the query planner. You want neither of that.
I reversed the order and made item_shipping_details the primary table. This will be much faster.
The LEFT JOIN between items and item_shipping_details was contradictory, because additional clauses require a row from both tables anyway. Simplified to plain JOIN.
Also makes the order of appearance of the first two tables irrelevant again.
Removed the brackets around the first JOIN, as that served no purpose.
Simplified (it.outbound != true OR it.outbound is null) to it.outbound IS NOT TRUE
SELECT i.shipping_charges, i.shipping_carrier, i.shipping_method,
i.tracking_number, i.origin_zip_code, i.origin_city,
i.origin_country, i.weight_value, i.weight_unit,
i.delivery_date, i.shipping_date, i.shipping_description,
i.delivery_zip_code, i.delivery_street_add, i.item_id,
i.start_at, i.end_at, i.id
FROM item_shipping_details i
JOIN items it ON it.id = i.item_id
LEFT JOIN users u on u.id = it.alert_user_id
WHERE i.id IN (35,602,1175,1176,1177,604,1178,1174,1165,1179,
930,1160,917,914,925,909,920,1147,910)
AND it.user_id = 4
AND it.outbound IS NOT TRUE
AND (it.alert_user_id IS NULL OR u.user_type IN (2,3))
Should considerably increase execution time ... performance. :)
Assuming you meant decrease query execution time, turning on indexing for the appropriate columns can greatly speed up result retrieval.
THIS PART OF YOUR QUERY IS TAKING TIME
IN (35,602,1175,1176,1177,604,1178,1174,1165,1179,
930,1160,917,914,925,909,920,1147,910)
YES "Subqueries" there are many ways:
Use JOIN() and less INCLUDE() in association.
Try to avoid subqueries and find([array])
Use cache
There may be more better options you may find below in rails doc
http://guides.rubyonrails.org/active_record_querying.html

Propel 1.5 How to make join with OR condition

I need to generate such SQL using Propel build criteria:
"SELECT *
FROM `table1`
LEFT JOIN table2 ON ( table1.OBJECT_ID = table2.ID )
LEFT JOIN table3 ON ( table1.OBJECT_ID = table3.ID )
LEFT JOIN table4 ON ( table4.USER_ID = table2.ID
OR table4.USER_ID = table3.AUTHOR_ID )"
Is it possible to make join with or condition? Or maybe some other ways?
Propel 1.5
Table1Query::create()
->leftJoinTable2()
->leftJoinTable3()
->useTable2Query()
->leftJoinTable4()
->endUse()
->condition('cond1', Table4::USER_ID . ' = ' . Table2::ID)
->condition('cond2', Table4::USER_ID . ' = ' . Table3::AUTHOR_ID)
->combine(array('cond1', 'cond2'), Criteria::LOGICAL_OR, 'onClause')
->setJoinCondition('Table4', 'onClause')
->find();
useTable2Query() is necessary because your information seems to imply that Table4 is related to Table2 and not to Table1, and so joining Table4 directly to Table1 will result in a series of fatal Propel errors. The "use" functionality bridges that relationship.
The first two joins (table2, table3) are easy, if I recall correctly. Just make table1.OBJECT_ID non-required in your schema, and the left join will be used automatically.
Not immediately sure about the OR join. If you get stuck, one way to do it is to use the above in a raw query, and then "hydrate" objects from the resultset. Another way (very good for complex queries that are a pain to express in an ORM) is to create a database view for the above, and then add a new table in your schema for the view. It's cheating a bit for sure, but for some really complex master-detail things I did in a large symfony project, it was great - and it made query debugging really easy as well.

Resources