Arel query issues using where and group - activerecord

In Rails 4, I have these 3 tables:
Users table with these columns:
-name
-email
Orders table with these columns:
-amount
-user_id
Items table with these columns:
-name
-description
OrderItems table with these columns:
order_id
item_id
Relations:
-The orderItems table is a joined table
-The user has many orders and an order belongs to a user.
Questions:
1) Find the 5 biggest orders (orders with the most items)
I think the query is:
OrderItem.group(:order_id).order(count(id) desc").limit(5).pluck(:order_id)
What is the group exactly doing? When I type in OrderItem.group(:order_id) only I Don't understand the output.
2) How do I find a user with the name "betty" AND "the email "betty#gmail.com". For this, do I need to write SQL inside my Arel?

OrderItem.group(:order_id) by itself won't produce valid SQL. group turns into an SQL GROUP BY statement which groups rows together if they share the same value for the column that is specified. GROUP BY needs to be used with a SELECT statement that has the columns that were in the GROUP BY or that are aggregate functions like COUNT.
Your full query is missing a quotation mark in the order clause. You'll want:
OrderItem.group(:order_id).order("count(id) desc").limit(5).pluck(:order_id)
To find a user with the name "betty" and the email "betty#gmail.com" you can use:
User.where(name: "betty", email: "betty#gmail.com")

Related

Oracle select rows from a query which are not exist in another query

Let me explain the question.
I have two tables, which have 3 columns with same data tpyes. The 3 columns create a key/ID if you like, but the name of the columns are different in the tables.
Now I am creating queries with these 3 columns for both tables. I've managed to independently get these results
For example:
SELECT ID, FirstColumn, sum(SecondColumn)
FROM (SELECT ABC||DEF||GHI AS ID, FirstTable.*
FROM FirstTable
WHERE ThirdColumn = *1st condition*)
GROUP BY ID, FirstColumn
;
SELECT ID, SomeColumn, sum(AnotherColumn)
FROM (SELECT JKM||OPQ||RST AS ID, SecondTable.*
FROM SecondTable
WHERE AlsoSomeColumn = *2nd condition*)
GROUP BY ID, SomeColumn
;
So I make a very similar queries for two different tables. I know the results have a certain number of same rows with the ID attribute, the one I've just created in the queries. I need to check which rows in the result are not in the other query's result and vice versa.
Do I have to make temporary tables or views from the queries? Maybe join the two tables in a specific way and only run one query on them?
As a beginner I don't have any experience how to use results as an input for the next query. I'm interested what is the cleanest, most elegant way to do this.
No, you most probably don't need any "temporary" tables. WITH factoring clause would help.
Here's an example:
with
first_query as
(select id, first_column, ...
from (select ABC||DEF||GHI as id, ...)
),
second_query as
(select id, some_column, ...
from (select JKM||OPQ||RST as id, ...)
)
select id from first_query
minus
select id from second_query;
For another result you'd just switch the tables, e.g.
with ... <the same as above>
select id from second_query
minus
select id from first_query

Oracle SQL - How to add a filter on a case field that I created?

I'm relatively new to Oracle SQL and have run into an issue where I'm trying to filter a report to only return records logged by a specific list of user names.
They are currently stored in the system in fields user.first_name and user.surname and I've created the following CAST field in the coding to join the two together:
CAST(USER.FIRST_NAME||' '||USER.SURNAME as VARCHAR (25)) as CUSTOMER
What I want to do now though is restrict it so that my query will only return records where the customer is in a pre-determined list that I can hard core into the SQL.
eg I only want to see records for :
Joe Bloggs,
John Doe,
A Nother
How do I do this in Oracle SQL?
Thanks
One option (as you said you hardcoded it) is
select *
from your_table
where customer in ('Joe Bloggs', 'John Doe', 'A Nother');
A better one is to store those customers into a separate table and join it with your_table:
insert into separate_table (name) values ('Joe Bloggs'); -- do the same for the rest
select *
from your_table y join separate_table s on s.name = y.first_name ||' '||i.surname;
Even better, use their IDs (because, there could be two John Doe persons; which one will you take)?
insert into separate_table (id) values (1123); -- this is Joe Bloggs
select *
from your_table y join separate_table s on s.id = y.id;

Display all the fields associated with the record using Impala

Suppose, I have a student table with some fields in impala. Imagine there is a field called total_mark and I should find the student details with maximum mark from each branch.
My table is like this :-
In this table I have to get the details of student with maximum marks from each department.
My query will be like this :-
select id,max(total_marks) from student_details group by department;
But using this query I can get only the id and total_marks. Provided there can be students with same name,age I can't group with fields like age,name .
So how should I query the table to get all the details of top student from each department ??
Thanks in advance.
You can make use of the JOIN concept
select stu.*
from student_details stu
join
( select department,max(total_marks) as max
from student_details
group by department
) rank
on stu.department=rank.department and stu.total_marks=rank.max;

Correlating data from two tables in Oracle using a third which maps them together

I'm trying to JOIN/UNION/whatever data from two tables based on a third which maps them together. Here is the idea:
Table USERS contains user ID, username, some other data.
Table GROUPS contains group ID, group name, some other data.
Table USERGROUPMAP contains a bunch of user IDs and group IDs mapped together which correspond to IDs in USERS and GROUPS. Each user can be in multiple groups, each group can have multiple users.
I have always done this by storing objects or CSV data in a single field, e.g. making a column in groups called MEMBERS and storing id1,id2,id3...but this is what I was presented with.
I can't change the schema...I know this has something to do with JOINs or UNIONs or something but my SQL is very rusty, so can anyone help out here?
My maybe semi-correct idea -
SELECT USERS.uid,
GROUPS.gid,
USERGROUPMAP.uid,
USERGROUPMAP.gid
FROM USERS,
GROUPS,
USERGROUPMAP
JOIN ON ((USERS.uid = USERGROUPMAP.uid) AND (GROUPS.gid = USERGROUPMAP.gid))
Any tips? :( .. Thanks guys.
Edit, expected IO
USERS table contains a bunch of UIDs ... 1,2,3,4,5, so on
GROUPS table contains a bunch of GIDs, 1000,1001,1002 and so on
USERGROUPMAP contains tuples corresponding to which users are in which groups, eg (1,1002) (2,1000) (5,1003) (5,1000)
I am trying to get a list of groups a user is in, so for this example I want to get two rows of 5,1003 and 5,1000 ... make sense?
Select a.userID, a.name, b.groupName
from USERS a, GROUPS b, USERGROUPMAP c
where c.userID = a.userID and
b.groupID = c.groupID and
c.userID = <searchID>
The userID you want to search is the searchID in the query. You can replace userID with groupID if you are listing users for a group.
Assuming there are no duplicates in USERS nor GROUPS, it's a simple join between the three tables:
SELECT
USERS.FIELD1,
USERS.FIELD2,
-- ...
USERS.FIELDN,
GROUPS.FIELD1,
GROUPS.FIELD2,
-- ...
GROUPS.FIELDN
FROM USERS
JOIN USERGROUPMAP ON USERS.UID = USERGROUPMAP.UID
JOIN GROUPS ON USERGROUPMAP.GID = GROUPS.GID

Getting latest record for each userid in rails 3.2

I have user with name, location, created_at as important fields in table.
I want to retrieve for each user the latest location,i.e, I want something like this:
username location created_at
abc New York 2012-08-18 16:18:57
xyz Mexico city 2012-08-18 16:18:57
abc Atlanta 2012-08-11 16:18:57
only input is UId(1,2) array of userids.please help me to accomplish this.I just want to know how to write query using active record query interface.
Generally, this should be a standard way to solve this kind of problems:
SELECT l1.user, l1.location
FROM locations l1
LEFT JOIN locations l2 ON l1.user = l2.user AND l2.created_at > l1.created_at
WHERE l2.id IS NULL
The idea is to join the table with itself, and find those rows which don't have any row with the same user and greater created_at.
Of course, you should have (user, created_at) index on your table.
Now you should see how would that be represented in AR interface.
When
u_id
is the array of user ids, then
u_id.map{|i| User.find(i).location}
should be an array of the users locations.
You can Use
User.where(:uid => [1,2,3]).maximum('location')
which will create something like
SELECT MAX(`users`.`location`) AS max_id FROM `users` WHERE `users`.`id` IN (1, 2,3)

Resources