How make multiple subqueries with Eloquent? - laravel

A have this code:
DB::select('
SELECT SUM(count) as count
FROM (
SELECT COUNT(*) AS count FROM ad_banners
UNION ALL
SELECT COUNT(*) AS count FROM ad_context
UNION ALL
SELECT COUNT(*) AS count FROM ad_content
UNION ALL
SELECT COUNT(*) AS count FROM ad_decoration
UNION ALL
SELECT COUNT(*) AS count FROM ad_front
UNION ALL
SELECT COUNT(*) AS count FROM ad_universal
) as ad'
);
How make this query using Eloquent ORM methods and will this make sense? Thanks in advance!
EDIT:
I wrote this code, but my attempts to use Eloquent ended to fail. I don't understand how make sub queries with union and count. I didn't wont to write my code for me, it will be enough a small example. And sorry for my bad english.

Have you tried using the DB::raw() method? Sometimes, if you know the SQL you want to use but don't know how to use Eloquent to accomplish it, you may use DB::raw() to get the results you need. Here's an example, you can tailor it to your needs:
$query = DB::connection('connection_name')->select(DB::raw("SELECT * FROM table WHERE ..."));
Also, connection_name can be found as you defined it in app/config/database.php in the connections array.
Hope that provides some insight. Without an idea of your models and relationships and what you're trying to accomplish, it would be hard to advise you on an Eloquent solution to this issue.

Related

SQL Developer Distinct gives ORA-00936

I try to create a query which gives me back how many customer has been registered to our system (using the REGISTERED_ID). However when a customer registrates he can then registrate again with a different car. I want to give back the amount of registers by month. I count the X__INSDATE because basicly I can count anything, all I need is a number. The error points to the DISTINCT, I tried to use having instead of where, but I may missed something.
I use Oracle SQL Developer 4.0.0.12
SELECT
TRUNC(X__INSDATE, 'MONTH') as HONAP,
COUNT(X__INSDATE),
DISTINCT REGISTERED_ID
FROM
DATABASE.data_history
WHERE
DATABASE.data_history.X__INSDATE >= to_date('2013-JÚL. -01', 'YYYY-MON-DD')
GROUP BY TRUNC(X__INSDATE, 'MONTH') ORDER BY HONAP;
Thank you for your help!
You need to apply an aggregate function to all the clauses not on the grup by.
Try with:
SELECT
TRUNC(X__INSDATE, 'MONTH') as HONAP,
COUNT(X__INSDATE),
COUNT(DISTINCT REGISTERED_ID)
Or by grouping as well by REGISTERED_ID

CodeIgniter Active Record select with 2 or more tables

I have this sql statement setup in my old code and want to move it over to active record, the problem that I'm phased with is how do I do a
SELECT news_items.id FROM
(SELECT news_items.* FROM news_items
JOIN feeds ON feeds.id=news_items.feed
LEFT JOIN news_item_country ON news_item_country.id=news_items.country
WHERE news_items.id=30758
ORDER BY date_item DESC )
AS news_items
GROUP BY news_items.id
ORDER BY date_item DESC
Trying to do this with Active Record, first I created the select that goes inside the select at least that is what I think needs to be done.
$news_items = $this->db->select('default_news_items.*')
->from('default_news_items ')
->join('default_feeds','default_feeds.id=default_news_items.feed')
->join('default_news_item_country','default_news_item_country.id=default_news_items.country','left')
->join('default_news_item_options','default_news_item_options.id=default_news_items.options','left')
->where($where)
->order_by('date_item DESC')
->limit($limit)
->get();
Next I create the actual select and reference the other select inside the from
if ($query = $this->db->select("
news_items.id,
->from($news_items)
->group_by('news_items.id')
->get()) {
It did not work, so I'm asking if someone have experiences with this and how to do it?
You can't do a subquery directly in native active record syntax. Check out this answer for a solution:
subquery in codeigniter active record
(The author wrote a library for active record subqueries http://labs.nticompassinc.com/CodeIgniter-Subqueries/ )
Without this or similar technique you need to keep your current select code at least for the subquery ($news_items).
Take a look at this answer of mine this might help how you can achieve it.
Using Mysql WHERE IN clause in codeigniter

EF: Is there way to force Linq using UNION instead of UNION ALL

I use Linq with entity-framework.
GetSet1<T>().Union(GetSet2<T>())
The GetSetX returns IQueryable.
The generated SQL is an UNION ALL. But I know a UNION is the good way to achieve my goal. Actually my workaround is:
GetSet1<T>().Union(GetSet2<T>()).Distinct()
in this case the generated sql is like :
select distinct Field...
from (
select distinct Field...
union all
select distinct Field...
) unionall
I know (because that is the way is was thinked) that
select Field...
union
select Field...
is the best query. So Is there a way (I can(t actually found) to have EntityFramework use UNION and not UNION ALL ?
==========
1: Adding the <T> for more precision
The Union() method should return the result without duplicates. Depending on the query, EF will generate either UNION ALL with DISTINCT or just UNION, so your explicit Distinct() is not necessary. The Linq equivalent of UNION ALL is Concat().
Besides that, EF has a history of generating inefficient SQL for queries. If you can, you should use EF 5.0 which has greatly improved query SQL generation.

hibernate oracle rownum issue

SELECT * FROM (
select *
from tableA
where ColumnA = 'randomText'
ORDER BY columnL ASC
) WHERE ROWNUM <= 25
on execution of this query, due to some Oracle optimization, the query takes about 14 minutes to execute . If I remove the where clause , the query executes in seconds. most of the columns of the table have indexes on them, including the ones mentioned above. I do not have much flexibility on the structure of the query as I use hibernate.
This query returns results instantly too, with the correct result:
SELECT *
FROM (
select *
from tableA,
dual
where ColumnA = 'randomText'
ORDER BY columnL ASC
) WHERE ROWNUM <= 25
is there something I can do, using hibernate?
UPDATE: I use EntityManager.createQuery(), and I use setMaxResults(25) and setFirstResult() too. the query above is what hibernate's query looks like, upon observation of logs
I don't get the explain plans exactly matched to your queries, but it seems oracle using a different index for the two queries.
Can you create an index containing columnA and columnL?
If you have an index only containing columnA, you MIGHT be able to drop that without a large effect on performance of other queries.
An alternative would be to add a hint to use the index used in the faster query. But this would require you to use native sql.
this means you are using hibernate/jpa? If so, I guess you are using the EntityManager.createNativeQuery() to create the query? Try removing your where-restriction and use the .setMaxResults(25) on the Query instead.
Anyways, why do you need the outer-select? Wouldn't
select *
from tableA
where ColumnA = 'randomText'
AND ROWNUM <= 25
ORDER BY columnL ASC
produce the desired results?

oracle-inline view

Why inline views are used..??
There are many different reasons for using inline views. Some things can't be done without inline views, for example:
1) Filtering on the results of an analytic function:
select ename from
( select ename, rank() over (order by sal desc) rnk
from emp
)
where rnk < 4;
2) Using ROWNUM on ordered results:
select ename, ROWNUM from
( select ename
from emp
order by ename
);
Other times they just make it easier to write the SQL you want to write.
The inline view is a construct in Oracle SQL where you can place a query in the SQL FROM, clause, just as if the query was a table name.
Inline views provide
Bind variables can be introduced inside the statement to limit the data
Better control over the tuning
Visibility into the code
To get top N ordered rows.
SELECT name, salary,
FROM (SELECT name, salary
FROM emp
ORDER BY salary DESC)
WHERE rownum <= 10;
An inline view can be regarded as an intermediate result set that contributes to the required data set in some way. Sometimes it is entirely a matter of improving maintainability of the code, and sometimes it is logically neccessary.
From the Oracle Database Concepts document there are the inline view concept definition:
An inline view is not a schema object.
It is a subquery with an alias
(correlation name) that you can use
like a view within a SQL statement.
About the subqueries look in Using Subqueries from the Oracle SQL Reference manual. It have a very nice pedagogic information.
Anyway, today is preferred to use the Subquery Factoring Clause that is a more powerfull way of use inline views.
As an example of all together:
WITH
dept_costs AS (
SELECT department_name, SUM(salary) dept_total
FROM employees e, departments d
WHERE e.department_id = d.department_id
GROUP BY department_name),
avg_cost AS
SELECT * FROM dept_costs
WHERE dept_total >
(SELECT avg FROM (SELECT SUM(dept_total)/COUNT(*) avg
FROM dept_costs)
)
ORDER BY department_name;
There you can see one of all:
An inline view query: SELECT SUM...
A correlated subquery: SELECT avg FROM...
A subquery factoring: dept_costs AS (...
What are they used for?:
To avoid creating an intermediate view object: CREATE VIEW ...
To simplify some queries that a view cannot be helpfull. For instance, when the view need to filter from the main query.
You will often use inline views to break your query up into logical parts which helps both readability and makes writing more complex queries a bit easier.
Jva and Tony Andrews provided some good examples of simple cases where this is useful such as Top-N or Pagination queries where you may want to perform a query and order its results before using that as a part of a larger query which in turn might feed a query doing some other processing, where the logic for these individual queries would be difficult to achieve in a single query.
Another case they can be very useful is if you are writing a query that joins various tables together and want to perform aggregation on some of the tables, separating group functions and the processing into different inline views before performing the joins makes managing cardinality a lot easier. If you want some examples, I would be happy to provide them to make it more clear.
Factored subqueries (where you list your queries in the WITH clause at the start of the query) and inline views also often bring performance benefits. If you need to access the results of the subquery multiple times, you only need to run it once and it can be materialized as a Global Temporary Table (how the optimizer acts isn't totally black and white so I won't go into it here but you can do your own research - for example, see http://jonathanlewis.wordpress.com/2007/07/26/subquery-factoring-2/)

Resources