Does anyone know how to SQL this query in Google Big Query? - sql

I have a first database in the following format:
transaction_time id
2009-12-12 12:12 12345
2009-12-12 12:13 12346
... ...
The second database is in the following format:
id name
12345 abc
12346 bcd
... ...
I would like to write a query in Standard SQL for Google Big Query to count all occurrences of the same id on the same date and then return the name for the occurence (as in an Excel VLOOKUP).
I think it would be something along the lines of:
SELECT
DATETIME "2008-12-25 15:30:00" as original,
DATETIME_TRUNC(DATETIME "2008-12-25 15:30:00", DAY) as truncated
select t2.name, t1.id
from table1 t1 join
table2 t2
on t2.id = t1.request_time
Can anybody confirm? Or is there a GROUP BY function in Standard SQL for Big Query? I couldn't seem to find one!
Thanks very much!

Is this what you want?
select date(t1.request_time) as dte, count(*)
from table1 t1 join
table2 t2
on t2.id = t1.request_time
group by dte
order by dte;
Of course Standard SQL supports GROUP BY -- it is a very functional database from a querying perspective.
Or this?
select t2.name, count(*)
from table1 t1 join
table2 t2
on t2.id = t1.request_time
where date(t1.request_date) = date('2008-12-25')
group by t2.name;

Related

SQL: Finding non-matches

my first table looks like the following (t1)
uid
car_id
s123
1234
p908
2345
q123
567
my second table looks like the following (t2):
uid
category
s123
honda
p908
mercedes
What I am trying to do is to find the uids (along with their car_id) from t1 that do not have a matching uid in t2. For example, the "q123" from t1 should be returned since it does not appear in t2. Any idea how this can be achieved?
Thank you!
SELECT uid, car_id
FROM t1
WHERE uid NOT IN (SELECT uid FROM t2 )
Using LEFT JOIN will bring back all the rows on the LEFT, regardless of a match on the right. Since you only want the non-matching, you could include only these in the WHERE clause.
SELECT t1.uid, t1.car_id, t2.category
FROM t1 LEFT JOIN t2 on t1.uid = t2.uid
WHERE t2.uid IS NULL
Or, you could use a NOT EXISTS
SELECT t1.uid, t1.car_id
FROM t1
WHERE NOT EXISTS (SELECT 1 FROM t2 WHERE t1.uid = t2.uid)
I have never used Google Bigquery, but going off the docs here, the syntax looks just like MS SQL. Also, here's the SQL Fiddle if you need it.

How to use a subquery result for another sql select?

I want to use the result of a sql query and send another query based on the result.
Exmaple (of course real live query is more complex):
table1: name, age
table2: name, age, field1, fieldN
First query:
select name, age from table1 where age > 18.
Now I'd like to find all entries from table2 that match the multiple resulting fields of the first query.
Important note: I want to retrieve the full rows of table2 where the match is.
But how?
If you want to automatically join based on matching column names, then you can use a NATURAL JOIN:
WITH query1 AS (
SELECT age, name FROM table1 WHERE age > 18
)
SELECT age, name, t2.field1, t2.fieldN
FROM table2 t2 NATURAL JOIN query1;
Now, while NATURAL JOIN is generally not recommended, as it is really weak because your queries using it can easily brake due to schema changes, it may be OK for hand ad-hoc queries, or for queries, like the above, where you can make the columns used explicit. In either case, I advise against it and use the common join style:
WITH query1 AS (
SELECT age, name FROM table1 WHERE age > 18
)
SELECT t2.age, t2.name, t2.field1, t2.fieldN
FROM table2 t2 JOIN query1 q1 ON t2.age = q1.age AND t2.name = t1.name;
Now I'd like to:
find
all entries from table2
that match the multiple resulting fields
of the first query
SELECT * -- find
FROM table2 t2 -- from t2
WHERE EXISTS (
SELECT * FROM table1 t1
WHERE t1.name = t2.name -- that match
AND t1.age = t2.age -- Huh? "multiple matching fields" ?
AND t1.age > 18 -- with the same condition
);
Actually this is what I was looking for, but thanks for any help:
select * from table2 where (name, age) IN (
select name, age from table1 where age > 18
)
Query build based on MS sql server
select t1.*
from table1 as t1
join table2 as t2 on t1.name=t2.name and t1.age=t2.age
where t2.age > 18

SQL Join based on dates- Table2.Date=Next date after Table1.Date

I have two seperate tables which I want to join based on Dates. However, I don't want the dates in the tables to be equal to one another I want the date (and accompanying value) from one table to be joined with the next date available after that date in the second table.
I've put an example of the problem below:
Table 1:
Date Value
2015-04-13 A
2015-04-10 B
2015-04-09 C
2015-04-08 D
Table 2:
Date Value
2015-04-13 E
2015-04-10 F
2015-04-09 G
2015-04-08 H
Desired Output Table:
Table1.Date Table2.Date Table1.Value Table2.Value
2015-04-10 2015-04-13 B E
2015-04-09 2015-04-10 C F
2015-04-08 2015-04-09 D G
I'm at a bit of an ends of where to even get going with this, hence the lack of my current SQL starting point!
Hopefully that is clear. I found this related question that comes close but I get lost on incorporating this into a join statment!!
SQL - Select next date query
Any help is much appreciated!
M.
EDIT- There is a consideration that is important in that the day will not always be simply 1 day later. They need to find the next day available, which was in the original question but Ive update my example to reflect this.
Since you want the next available date, and that might not necessarily be the following date (eg. date + 1) you'll want to use a correlated subquery with either min or top 1.
This will give you the desired output:
;WITH src AS (
SELECT
Date,
NextDate = (SELECT MIN(Date) FROM Table2 WHERE Date > t1.Date)
FROM table1 t1
)
SELECT src.Date, src.NextDate, t1.Value, t2.Value
FROM src
JOIN Table1 t1 ON src.Date = t1.Date
JOIN Table2 t2 ON src.NextDate = t2.Date
WHERE src.NextDate IS NOT NULL
ORDER BY src.Date DESC
Sample SQL Fiddle
try this
select [Table 1].Date,[Table 1].Value,[Table 2].date,[Table 2].Value
from [Table 1]
join [Table 1]
on dateadd(dd,1,[Table 1].date) = [Table 2].date
i'd go with an outer apply:
SELECT t1.*, t2.*
FROM Table1 t1
CROSS APPLY (
SELECT TOP 1 *
FROM Table2 t2
WHERE t2.Date > t1.Date
ORDER BY t2.Date) t2
ORDER BY t1.Date DESC

Joining two columns but keeping multiple instances in SQL

I am using SQL 2008 and am having a problem.
I have 3 different tables and here is a sample of my code.
SELECT DISTINCT Name Age
FROM Table1
LEFT JOIN Table2
ON Table1.ID = Table2.ID
This returns something like this:
Name Age
tom 12
ben 23
ian 12
I have another query
SELECT Name
FROM Table3
This returns this:
ian 12
ian 12
ian 12
I want to verify that if a name and age are in name from the first query and is in the second query Table3.name it will return something like this:
ian 12
ian 12
ian 12
I have been trying Join and Union on these two columns but so far have been only been able to get it to return. Any suggestions?
ian 12
This might be able to be simplified (need to see your table structures and sample data), but given your queries, a subquery should work for you:
SELECT T3.Name, T3.Age
FROM Table3 T3
JOIN (
SELECT DISTINCT Name, Age
FROM Table1
LEFT JOIN Table2
ON Table1.ID = Table2.ID
) T ON T3.Name = T.Name AND T3.Age = T.Age
SQL Fiddle Demo
First you pronounce your problem - you want to get all records for which combination of Name and Age exists in recordset of distinct Name and Age from join. Then you use power of declarative language and a little of CTE to get your solution:
;with CTE as (
select distinct Name, Age
from Table1 as T1
inner join Table2 as T2 on T2.ID = T1.ID
)
select *
from Table3 as T3
where exists (select * from CTE as C where C.Name = T3.Name and C.Age = T3.Age)
SQL FIDDLE EXAMPLE to fiddle with query

SQL nested query

I have a table like below
id name dependency
-----------------------
1 xxxx 0
2 yyyy 1
3 zzzz 2
4 aaaaaa 0
5 bbbbbb 4
6 cccccc 5
the list goes on. I want to select group of rows from this table , by giving the name of 0 dependency in where clause of SQL and till it reaches a condition where there is no more dependency. (For ex. rows 1,2, 3 forms a group, and rows 4,5,6 is another group) .please help
Since you did not specify a product, I'll go with features available in the SQL specification. In this case, I'm using a common-table expression which are supported by many database products including SQL Server 2005+ and Oracle (but not MySQL):
With MyDependents As
(
Select id, name, 0 As level
From MyTable
Where dependency = 0
And name = 'some value'
Union All
Select T.id, T.name, T.Level + 1
From MyDependents As D
Join MyTable As T
On T.id = D.dependency
)
Select id, name, level
From MyDependents
Another solution which does not rely on common-table expressions but does assume a maximum level of depth (in this case two levels below level 0) would something like
Select T1.id, T1.name, 0 As level
From MyTable As T1
Where T1.name = 'some value'
Union All
Select T2.id, T2.name, 1
From MyTable As T1
Join MyTable As T2
On T2.Id = T1.Dependency
Where T1.name = 'some value'
Union All
Select T3.id, T3.name, 2
From MyTable As T1
Join MyTable As T2
On T2.Id = T1.Dependency
Join MyTable As T3
On T3.Id = T2.Dependency
Where T1.name = 'some value'
Sounds like you want to recursively query your table, for which you will need a Common Table Expression (CTE)
This MSDN article explains CTEs very well. They are confusing at first but surprisingly easy to implement.
BTW this is obviously only for SQL Server, I'm not sure how you'd achieve that in MySQL.
This is the first thing that came to mind. It can be probably done more directly/succinctly, I'll try to dwell on it a little.
SELECT *
FROM table T1
WHERE T1.id >=
(SELECT T2.id FROM table T2 WHERE T2.name = '---NAME HERE---')
AND T1.id <
(SELECT MIN(id)
FROM table T3
WHERE T3.dependency = 0 AND T3.id > T2.id)
If you can estimate a max depth, this works out to something like:
SELECT
COALESCE(t4.field1, t3.field1, t2.field1, t1.field1, t.field1),
COALESCE(t4.field2, t3.field2, t2.field2, t1.field2, t.field2),
COALESCE(t4.field3, t3.field3, t2.field3, t1.field3, t.field3),
....
FROM table AS t
LEFT JOIN table AS t1 ON t.dependency = t1.id
LEFT JOIN table AS t2 ON t1.dependency = t2.id
LEFT JOIN table AS t3 ON t2.dependency = t3.id
LEFT JOIN table AS t4 ON t3.dependency = t4.id
....
This is a wild guess just to be different, but I think it's kind of pretty, anyway. And it's at least as portable as any of the others. But I don't want to look to closely; I'd want to use sensible data, start testing, and check for sensible results.
Hierarchical query will do:
SELECT *
FROM your_table
START WITH id = :id_of_group_header_row
CONNECT BY dependency = PRIOR id
Query works like this:
1. select all rows satisfying START WITH condition (this rows are roots now)
2. select all rows satisfying CONNECT BY condition,
keyword PRIOR means this column's value will be taken from the root row
3. consider rows selected on step 2 to be roots
4. go to step 2 until there are no more rows