Blog Archive

Monday, August 5, 2019

SQL learning notes

USING Keyword vs ON clause - MYSQL 


https://stackoverflow.com/questions/13750152/using-keyword-vs-on-clause-mysql

The USING clause
The USING clause is used if several columns share the same name but you don’t want to join using all of these common columns. The columns listed in the USING clause can’t have any qualifiers in the statement, including the WHERE clause.
The ON clause
The ON clause is used to join tables where the column names don’t match in both tables. The join conditions are removed from the filter conditions in the WHERE clause.

https://leetcode.com/problems/combine-two-tables/

175. Combine Two Tables
Table: Person
+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| PersonId    | int     |
| FirstName   | varchar |
| LastName    | varchar |
+-------------+---------+
PersonId is the primary key column for this table.
Table: Address
+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| AddressId   | int     |
| PersonId    | int     |
| City        | varchar |
| State       | varchar |
+-------------+---------+
AddressId is the primary key column for this table.

Write a SQL query for a report that provides the following information for each person in the Person table, regardless if there is an address for each of those people:
FirstName, LastName, City, State
# Write your MySQL query statement below
select FirstName, LastName, City, State #note, no database name used here since no ambiguity
from Person left join Address
on Person.PersonId = Address.PersonId
;


577Employee Bonus
https://leetcode.com/problems/employee-bonus/

Select all employee's name and bonus whose bonus is < 1000.
Table:Employee
+-------+--------+-----------+--------+
| empId |  name  | supervisor| salary |
+-------+--------+-----------+--------+
|   1   | John   |  3        | 1000   |
|   2   | Dan    |  3        | 2000   |
|   3   | Brad   |  null     | 4000   |
|   4   | Thomas |  3        | 4000   |
+-------+--------+-----------+--------+
empId is the primary key column for this table.
Table: Bonus
+-------+-------+
| empId | bonus |
+-------+-------+
| 2     | 500   |
| 4     | 2000  |
+-------+-------+
empId is the primary key column for this table.
Example ouput:
+-------+-------+
| name  | bonus |
+-------+-------+
| John  | null  |
| Dan   | 500   |
| Brad  | null  |
+-------+-------+
# Write your MySQL query statement below
#select empId, name, bonus #ERR,  Column 'empId' in field list is ambiguous
#select Employee.empId, name, bonus #ERR,  Column 'empId' in field list is not need
#select Employee.name, Bonus.bonus #ok
select name, bonus #ok
from Employee
left outer join Bonus
on Employee.empId = Bonus.empId
#where Bonus.bonus between 0 and 1000 or bonus is null #ok, not best
where bonus < 1000 OR bonus IS NULL
;

1082Sales Analysis I

Table: Product
+--------------+---------+
| Column Name  | Type    |
+--------------+---------+
| product_id   | int     |
| product_name | varchar |
| unit_price   | int     |
+--------------+---------+
product_id is the primary key of this table.
Table: Sales
+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| seller_id   | int     |
| product_id  | int     |
| buyer_id    | int     |
| sale_date   | date    |
| quantity    | int     |
| price       | int     |
+------ ------+---------+
This table has no primary key, it can have repeated rows.
product_id is a foreign key to Product table.

Write an SQL query that reports the best seller by total sales price, If there is a tie, report them all.
The query result format is in the following example:
Product table:
+------------+--------------+------------+
| product_id | product_name | unit_price |
+------------+--------------+------------+
| 1          | S8           | 1000       |
| 2          | G4           | 800        |
| 3          | iPhone       | 1400       |
+------------+--------------+------------+

Sales table:
+-----------+------------+----------+------------+----------+-------+
| seller_id | product_id | buyer_id | sale_date  | quantity | price |
+-----------+------------+----------+------------+----------+-------+
| 1         | 1          | 1        | 2019-01-21 | 2        | 2000  |
| 1         | 2          | 2        | 2019-02-17 | 1        | 800   |
| 2         | 2          | 3        | 2019-06-02 | 1        | 800   |
| 3         | 3          | 4        | 2019-05-13 | 2        | 2800  |
+-----------+------------+----------+------------+----------+-------+

Result table:
+-------------+
| seller_id   |
+-------------+
| 1           |
| 3           |
+-------------+
Both sellers with id 1 and 3 sold products with the most total price of 2800.
# Write your MySQL query statement below
SELECT seller_id
FROM Sales
GROUP BY seller_id
HAVING sum(price) = 
(
    SELECT sum(price)
    FROM sales
    group by seller_id
    order by sum(price) desc
    limit 1
)
#way2:
SELECT seller_id
FROM Sales
GROUP BY seller_id
Having SUM(price)=(SELECT SUM(price)AS total
FROM Sales S
GROUP BY seller_id
ORDER BY total DESC
LIMIT 1)

1083Sales Analysis II

Table: Product
+--------------+---------+
| Column Name  | Type    |
+--------------+---------+
| product_id   | int     |
| product_name | varchar |
| unit_price   | int     |
+--------------+---------+
product_id is the primary key of this table.
Table: Sales
+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| seller_id   | int     |
| product_id  | int     |
| buyer_id    | int     |
| sale_date   | date    |
| quantity    | int     |
| price       | int     |
+------ ------+---------+
This table has no primary key, it can have repeated rows.
product_id is a foreign key to Product table.

Write an SQL query that reports the buyers who have bought S8 but not iPhone. Note that S8 and iPhone are products present in the Product table.
The query result format is in the following example:
Product table:
+------------+--------------+------------+
| product_id | product_name | unit_price |
+------------+--------------+------------+
| 1          | S8           | 1000       |
| 2          | G4           | 800        |
| 3          | iPhone       | 1400       |
+------------+--------------+------------+

Sales table:
+-----------+------------+----------+------------+----------+-------+
| seller_id | product_id | buyer_id | sale_date  | quantity | price |
+-----------+------------+----------+------------+----------+-------+
| 1         | 1          | 1        | 2019-01-21 | 2        | 2000  |
| 1         | 2          | 2        | 2019-02-17 | 1        | 800   |
| 2         | 1          | 3        | 2019-06-02 | 1        | 800   |
| 3         | 3          | 3        | 2019-05-13 | 2        | 2800  |
+-----------+------------+----------+------------+----------+-------+

Result table:
+-------------+
| buyer_id    |
+-------------+
| 1           |
+-------------+
The buyer with id 1 bought an S8 but didn't buy an iPhone. The buyer with id 3 bought both.

# Write your MySQL query statement below
/* Way1: ok
select distinct buyer_id
from sales join product using(product_id)
where product_name = 'S8'
and buyer_id not in (select distinct buyer_id
                    from sales join product using(product_id)
                    where product_name = 'iPhone' )
*/
SELECT s.buyer_id
FROM Sales AS s INNER JOIN Product AS p
ON s.product_id = p.product_id
GROUP BY s.buyer_id
HAVING SUM(CASE WHEN p.product_name = 'S8' THEN 1 ELSE 0 END) > 0
AND SUM(CASE WHEN p.product_name = 'iPhone' THEN 1 ELSE 0 END) = 0;

1084Sales Analysis III


Table: Product
+--------------+---------+
| Column Name  | Type    |
+--------------+---------+
| product_id   | int     |
| product_name | varchar |
| unit_price   | int     |
+--------------+---------+
product_id is the primary key of this table.
Table: Sales
+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| seller_id   | int     |
| product_id  | int     |
| buyer_id    | int     |
| sale_date   | date    |
| quantity    | int     |
| price       | int     |
+------ ------+---------+
This table has no primary key, it can have repeated rows.
product_id is a foreign key to Product table.

Write an SQL query that reports the products that were only sold in spring 2019. That is, between 2019-01-01 and 2019-03-31 inclusive.
The query result format is in the following example:
Product table:
+------------+--------------+------------+
| product_id | product_name | unit_price |
+------------+--------------+------------+
| 1          | S8           | 1000       |
| 2          | G4           | 800        |
| 3          | iPhone       | 1400       |
+------------+--------------+------------+

Sales table:
+-----------+------------+----------+------------+----------+-------+
| seller_id | product_id | buyer_id | sale_date  | quantity | price |
+-----------+------------+----------+------------+----------+-------+
| 1         | 1          | 1        | 2019-01-21 | 2        | 2000  |
| 1         | 2          | 2        | 2019-02-17 | 1        | 800   |
| 2         | 2          | 3        | 2019-06-02 | 1        | 800   |
| 3         | 3          | 4        | 2019-05-13 | 2        | 2800  |
+-----------+------------+----------+------------+----------+-------+

Result table:
+-------------+--------------+
| product_id  | product_name |
+-------------+--------------+
| 1           | S8           |
+-------------+--------------+
The product with id 1 was only sold in spring 2019 while the other two were sold after.

# Write your MySQL query statement below
#Solution1:
SELECT s.product_id, product_name
FROM Sales s
LEFT JOIN Product p
ON s.product_id = p.product_id
GROUP BY s.product_id
HAVING MIN(sale_date) >= CAST('2019-01-01' AS DATE) AND
       MAX(sale_date) <= CAST('2019-03-31' AS DATE)

#Solution2:
SELECT product_id, product_name
FROM Sales
LEFT JOIN Product  #same as JOIN Product
Using(product_id)
GROUP BY product_id
HAVING MIN(sale_date) >= '2019-01-01' AND MAX(sale_date) <= '2019-03-31' 

1142User Activity for the Past 30 Days II

Table: Activity
+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| user_id       | int     |
| session_id    | int     |
| activity_date | date    |
| activity_type | enum    |
+---------------+---------+
There is no primary key for this table, it may have duplicate rows.
The activity_type column is an ENUM of type ('open_session', 'end_session', 'scroll_down', 'send_message').
The table shows the user activities for a social media website.
Note that each session belongs to exactly one user.

Write an SQL query to find the average number of sessions per user for a period of 30 days ending 2019-07-27 inclusively, rounded to 2 decimal places. The sessions we want to count for a user are those with at least one activity in that time period.
The query result format is in the following example:
Activity table:
+---------+------------+---------------+---------------+
| user_id | session_id | activity_date | activity_type |
+---------+------------+---------------+---------------+
| 1       | 1          | 2019-07-20    | open_session  |
| 1       | 1          | 2019-07-20    | scroll_down   |
| 1       | 1          | 2019-07-20    | end_session   |
| 2       | 4          | 2019-07-20    | open_session  |
| 2       | 4          | 2019-07-21    | send_message  |
| 2       | 4          | 2019-07-21    | end_session   |
| 3       | 2          | 2019-07-21    | open_session  |
| 3       | 2          | 2019-07-21    | send_message  |
| 3       | 2          | 2019-07-21    | end_session   |
| 3       | 5          | 2019-07-21    | open_session  |
| 3       | 5          | 2019-07-21    | scroll_down   |
| 3       | 5          | 2019-07-21    | end_session   |
| 4       | 3          | 2019-06-25    | open_session  |
| 4       | 3          | 2019-06-25    | end_session   |
+---------+------------+---------------+---------------+

Result table:
+---------------------------+ 
| average_sessions_per_user |
+---------------------------+ 
| 1.33                      |
+---------------------------+ 
User 1 and 2 each had 1 session in the past 30 days while user 3 had 2 sessions so the average is (1 + 1 + 2) / 3 = 1.33.
# Write your MySQL query statement below
select round(ifnull(count(distinct session_id)/count(distinct user_id),0),2) as average_sessions_per_user
from activity
where activity_date <= '2019-07-27' and activity_date > '2019-06-27'

#Way2:

select round(coalesce(avg(n_session),0),2) average_sessions_per_user
    from
    (select count(distinct session_id) n_session
        from activity
        where activity_date between '2019-06-28' and '2019-07-27'
        group by user_id) a;     

Saturday, August 3, 2019

NAMING CONVENTIONS FOR KEY-VALUE MAPS

How do you name Maps? Maps of the key-value pair variety rather than the hip Google-enabled map of the USA.
There seems to be no convention. Even for individual programming languages, there seems to be no convention enshrined in the culture, although some languages naturally favor shorter names than others.
Let’s say I’m mapping each captain to their respective team. There are several naming strategies:
·        values as in teams. Succinct, but doesn’t tell you what the keys represent. It’s usually not apparent from the declaration (e.g. Map) or initialization (e.g. new HashMap()), so you’d have to go and find code that uses it or read a comment. So it would be a particularly choice if used as a parameter for a published API.
·        mapFromKeysToValues as in mapFromCaptainsToTeams. Says it all, if a bit verbose.
·        mapOfKeysToValues as in mapOfCaptainsToTeams. Ditto.
·        keysToValues as in captainsToTeams. More succinct, but the shorthand form belies that its a noun. So someone reading “print(captainsToTeams)” will probably interpret it as “print the map of captains to teams”. I’d rather the structure be more clear at a glance.
I used “keyToValues” for a long time, but I’ve recently switched to this:
·        valuesByKeys as in teamsByCaptains. If you’re going to include both key and value, this seems to read best. At a high level, you can read it as just “teams”, so anything that’s performed on it is being performed on teams. The “...byCaptains” prefix reads as it should do: a less significant qualifier that follows the teams around to help someone understand the structure if they need to.
In all cases, I’ve assumed plural. There’s certainly an argument to be made for singular form, as in captainToTeam, or any combination. I find plural works best in most contexts.
With template-style structures such as Java 1.5 offers, values might be the way to go. With a name like teams, you can’t immediately tell the key type, but you can always locate the type in the declaration. That’s different to the pre-1.5 situation, and dynamic languages, where you have to locate actual code. With the key type being part of the map type, simply values is probably the right trade-off. Unless the key type tells you little about the meaning of the key, such as String, in which case I’m still running with keysToValues.




Reference:

Sunday, July 28, 2019

How to solve the error with passing const std::unordered_map or passing const std::map

// Example program
#include <iostream> #include <string> #include<unordered_map> using namespace std; void printMap(const unordered_map<int, int> m){ for(auto item:m){ cout<< item.first << " " << item.second<<" "; cout<< item.first << " " << m[item.first]<<endl; //cout<< item.first << " " << m.at(item.first)<<endl; } return; } int main() { unordered_map<int, int> m; m[0]=10; m[1]=20; printMap(m); return 0; }


Question: How to solve the following error:
9:49: error: passing 'const std::unordered_map<int, int>' as 'this' argument of
'std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::mapped_type&
std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator[](const key_type&)
[with _Key = int; _Tp = int; _Hash = std::hash<int>; _Pred = std::equal_to<int>;
_Alloc = std::allocator<std::pair<const int, int> >;
std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::mapped_type = int;
std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::key_type = int]'
discards qualifiers [-fpermissive]


Answer:
using at() to access the element of map or unordered_map
Solution:
cpp.sh/7rmyz


Sunday, July 21, 2019

Constant pointer vs Pointer to constant [C++]



https://stackoverflow.com/questions/21476869/constant-pointer-vs-pointer-to-constant


const int* ptr; 
declares ptr a pointer to const int type. You can modify ptr itself but the object pointed to by ptr shall not be modified.
const int a = 10;
const int* ptr = &a;  
*ptr = 5; // wrong
ptr++;    // right  
While
int * const ptr;  
declares ptr a const pointer to int type. You are not allowed to modify ptr but the object pointed to by ptr.
int a = 10;
int *const ptr = &a;  
*ptr = 5; // right
ptr++;    // wrong
Generally I would prefer the declaration like this which make it easy to read and understand (read from right to left):
int const  *ptr; // ptr is a pointer to constant int 
int *const ptr;  // ptr is a constant pointer to int