Join, group and count in the same query - asp.net

I have these tables in my database:
TOTAL TABLE:
total_table_id | person_id | car_id | year
----------------|-----------|-----------|------
0 | 1 | 4 | 2015
1 | 1 | 2 | 2017
2 | 2 | 0 | 2017
3 | 3 | 3 | 2017
4 | 3 | 4 | 2015
PERSON TABLE:
person_id | name | age
------------|-------|-----
0 | John | 26
1 | Anna | 41
2 | Sam | 33
3 | Tim | 33
CAR TABLE:
car_id | model | color
--------|-------|-------
0 | A | red
1 | B | blue
2 | B | white
3 | D | red
4 | C | black
And what I want after select the year in a dropdown is to get something like this:
2017:
color | age | cars_count
--------|-------|------------
red | 33 | 2
white | 41 | 1
This is the query that I have for the moment:
from a in total
join b in person
on a.person_id equals b.person_id
join c in car
on a.car_id equals c.car_id
select new
{
color = c.color,
age = b.age,
cars_count = ? // <--------This is what I don't know how to get it
}).ToList();
Any tips?

You should use group by statement
var answer = (from total in totalTable
where total.year == 2017
join car in carTable on total.car_id equals car.car_id
join person in personTable on total.person_id equals person.person_id
group person by car.color into sub
select new
{
color = sub.Key,
age = sub.Max(x => x.age),
//or age = sub.Min(x => x.age),
//or age = sub.First().age,
count = sub.Count()
}).ToList();

Related

SQL LEFT JOIN not pulling intended data

I have the below tables:
CATEGORIES:
id | name | category_group | cate_type_id
1 | Entertainment | Entertainment | 1
2 | Electricity | Utilities | 8
3 | Water | Utilities | 8
4 | Rent | Living Exp | 6
5 | credit card | Finance | 5
BUDGET-ITEMS:
id | budget_id | cat_id | category_group| budget_yr | budget_01 | budget_02 | ... | budget_12
1 | 1 | 1 | Entertainment | 2022 | 500 | |
2 | 1 | 2 | Utilities | 2022 | 1500 | |
3 | 1 | 3 | Utilities | 2022 | | 250 |
I want to pull all items from Category table with mapping budget columns. Below is my JOIN.
SELECT c.id as base_id,c.name,c.category_type_id, c.category_group as base_group, b.*
FROM category c
LEFT JOIN budget_items b ON c.id = b.category_id
WHERE c.category_type_id NOT IN (5)
ORDER BY c.category_type_id, c.category_group ASC
I expect the below output:
id | budget_id | cat_id | catgroup | budget_yr | budget_01 | budget_02 | ... | budget_12
1 | 1 | 1 | Entertainment | 2022 | 500 | |
2 | 1 | 2 | Utilities | 2022 | 1500 | |
3 | 1 | 3 | Utilities | 2022 | | 250 |
4 | 1 | 4 | Living Exp | 2022 | | |
However, I get like below (truncated base* columns here for space):
id | budget_id | cat_id | catgroup | budget_yr | budget_01 | budget_02 | ... | budget_12
1 | 1 | 1 | Entertainment | 2022 | 500 | |
2 | 1 | 2 | Utilities | 2022 | | 1500 |
3 | 1 | 3 | Utilities | 2022 | | |
4 | 1 | 4 | Living Exp | 2022 | | |
My query looks OK, not sure where it is going wrong. Does anyone see the issue?
Thanks in advance for your kind help.
Edit:
I have truncated some columns for space here. the problem is the values are aligned to different budget columns. I get the columns correctly from the left table.
Edit:
Thanks to everyone who pitched in to help, I finally figured the issue was with my data. The query was actually working fine. This community is amazing.
Not sure what you're doing, but it seems to work as expected for me:
Schema (SQLite v3.30)
CREATE TABLE items (
`id` INTEGER,
`budget_id` INTEGER,
`cat_id` INTEGER,
`catgroup` VARCHAR(13),
`budget_yr` INTEGER,
`budget_01` INTEGER,
`budget_02` INTEGER
);
INSERT INTO items
(`id`, `budget_id`, `cat_id`, `catgroup`, `budget_yr`, `budget_01`, `budget_02`)
VALUES
('1', '1', '1', 'Entertainment', '2022', '500', null),
('2', '1', '2', 'Utilities', '2022', '1500', null),
('3', '1', '3', 'Utilities', '2022', null, '250');
CREATE TABLE cats (
`id` INTEGER,
`name` VARCHAR(13),
`category_group` VARCHAR(13),
`cate_type_id` INTEGER
);
INSERT INTO cats
(`id`, `name`, `category_group`, `cate_type_id`)
VALUES
('1', 'Entertainment', 'Entertainment', '1'),
('2', 'Electricity', 'Utilities', '8'),
('3', 'Water', 'Utilities', '8'),
('4', 'Rent', 'Living Exp', '6'),
('5', 'credit card', 'Finance', '5');
Query
SELECT c.id
, budget_id
, cat_id
, catgroup
, budget_yr
, budget_01
, budget_02
FROM cats c
LEFT JOIN items i ON c.id = i.cat_id
WHERE c.cate_type_id <> 5;
id
budget_id
cat_id
catgroup
budget_yr
budget_01
budget_02
1
1
1
Entertainment
2022
500
2
1
2
Utilities
2022
1500
3
1
3
Utilities
2022
250
4
View on DB Fiddle

How do you assign groups to larger groups dpylr

I would like to assign groups to larger groups in order to assign them to cores for processing. I have 16 cores.This is what I have so far
test<-data_extract%>%group_by(group_id)%>%sample_n(16,replace = TRUE)
This takes staples OF 16 from each group.
This is an example of what I would like the final product to look like (with two clusters),all I really want is for the same group id to belong to the same cluster as a set number of clusters
________________________________
balance | group_id | cluster|
454452 | a | 1 |
5450441 | a | 1 |
5444531 | b | 1 |
5404051 | b | 1 |
5404501 | b | 1 |
5404041 | b | 1 |
544251 | b | 1 |
254252 | b | 1 |
541254 | c | 2 |
54123254 | d | 1 |
542541 | d | 1 |
5442341 | e | 2 |
541 | f | 1 |
________________________________
test<-data%>%group_by(group_id)%>% mutate(group = sample(1:16,1))

Master-Detail show data SQL

I'm working with SQL Server and I have this 3 tables
STUDENTS
| id | student |
-------------
| 1 | Ronald |
| 2 | Jenny |
SCORES
| id | score | period | student |
| 1 | 8 | 1 | 1 |
| 2 | 9 | 2 | 1 |
PERIODS
| id | period |
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
And I want a query that returns this result:
| student | score1 | score2 | score3 | score4 |
| Ronald | 8 | 9 | null | null |
| Jenny | null | null | null | null |
As you can see, the number of scores depends of the periods because sometimes it can be 4 o 3 periods.
I don't know if I have the wrong idea or should I make this in the application, but I want some help.
You need to PIVOT your data e.g.
select Y.Student, [1], [2], [3], [4]
from (
select T.Student, P.[Period], S.Score
from Students T
cross join [Periods] P
left join Scores S on S.[Period] = P.id and S.Student = T.id
) X
pivot
(
sum(Score)
for [Period] in ([1],[2],[3],[4])
) Y
Reference: https://learn.microsoft.com/en-us/sql/t-sql/queries/from-using-pivot-and-unpivot?view=sql-server-20

R data.table add new column with query for each row

I have 2 R data.tables in R like so:
first_table
id | first | trunc | val1
=========================
1 | Bob | Smith | 10
2 | Sue | Goldm | 20
3 | Sue | Wollw | 30
4 | Bob | Bellb | 40
second_table
id | first | last | val2
==============================
1 | Bob | Smith | A
2 | Bob | Smith | B
3 | Sue | Goldman | A
4 | Sue | Goldman | B
5 | Sue | Wollworth | A
6 | Sue | Wollworth | B
7 | Bob | Bellbottom | A
8 | Bob | Bellbottom | B
As you can see, the last names in the first table are truncated. Also, the combination of first and last name is unique in the first table, but not in the second. I want to "join" on the combination of first name and last name under the incredibly naive assumptions that
first,last uniquely defines a person
that truncation of the last name does not introduce ambiguity.
The result should look like this:
id | first | trunc | last | val1
=======================================
1 | Bob | Smith | Smith | 10
2 | Sue | Goldm | Goldman | 20
3 | Sue | Wollw | Wollworth | 30
4 | Bob | Bellb | Bellbottom | 40
Basically, for each row in table_1, I need to find a row that back fills the last name.
For Each Row in first_table:
Find the first row in second_table with:
matching first_name & trunc is a substring of last
And then join on that row
Is there an easy vectorized way to accomplish this with data.table?
One approach is to join on first, then filter based on the substring-match
first_table[
unique(second_table[, .(first, last)])
, on = "first"
, nomatch = 0
][
substr(last, 1, nchar(trunc)) == trunc
]
# id first trunc val1 last
# 1: 1 Bob Smith 10 Smith
# 2: 2 Sue Goldm 20 Goldman
# 3: 3 Sue Wollw 30 Wollworth
# 4: 4 Bob Bellb 40 Bellbottom
Or, do the truncation on the second_table to match the first, then join on both columns
first_table[
unique(second_table[, .(first, last, trunc = substr(last, 1, 5))])
, on = c("first", "trunc")
, nomatch = 0
]
## yields the same answer

SQLite join selection from the same table as two columns

I have one table 'positions' with columns:
id | session_id | keyword_id | position
and some rows in it:
10 rows with session_id = 1
and 10 with session_id = 2.
As a result of the query I need a table like this:
id | keyword_id | position1 | position2
where 'position1' is a column with values that had session_id = 1 and 'position2' is a column with values that had session_id = 2.
The result set should contain 10 records.
Sorry for my bad English.
Data examle:
id | session_id | keyword_id | position
1 | 1 | 1 | 2
2 | 1 | 2 | 3
3 | 1 | 3 | 0
4 | 1 | 4 | 18
5 | 2 | 5 | 9
6 | 2 | 1 | 0
7 | 2 | 2 | 14
8 | 2 | 3 | 2
9 | 2 | 4 | 8
10 | 2 | 5 | 19
Assuming that you wish to combine positions with the same id, from the two sessions, then the following query should to the trick:
SELECT T1.keyword_id
, T1.position as Position1
, T2.position as Position2
FROM positions T1
INNER JOIN positions T2
ON T1.keyword_id = T2.keyword_id -- this will match positions by [keyword_id]
AND T1.session_id = 1
AND T2.session_id = 2

Resources