how to view data from different tables - sql

I have 4 tables : tbl_info, tbl_owner, tbl_accounts, tbl_billing
--tbl_info: information
info_id | fname | lname
10 | ron | lum
--tbl_owner: owner
own_id | owner_info_id |property_type
01 | 10 | land
--tbl_all_property: landfindings
property_id | property_owner_id | owner_id | OR_no
1 | 101 | 10 | 987
2 | 101 | 10 | 874
3 | 101 | 10 | 875
--tbl_billing: billing
bill_id | status | total | property_id
1 | not paid | 100 | 1
my question is how to view the value of "fname,lname,status,total" when I enter ORNo = '875'
since the 3 OR_no was owned by the same owner.

select a.fname,
a.lname,
d.status,
d.total
from tbl_info a
inner join tbl_owner b
on a.info_id=b.owner_info_id
inner join tbl_all_property c
on c.owner_id=b.owner_info_id
inner join tbl_billing d
on d.property_id=c.property_id
where c.OR_no='875'

Related

How to get additional column with row count using two different tables?

In my database I have usergroup, usergroup_user tables. I want to make a SQL query which can result something like result(group_id, name, date, users_count).
usergroup table
------------------
| group_id| name |
------------------
| 10 |test1 |
| 11 |test2 |
| 12 |test3 |
------------------
usergroup_user table
---------------------
|group_id | user_id |
---------------------
| 10 | 100 |
| 10 | 200 |
| 10 | 250 |
| 11 | 250 |
| 11 | 700 |
---------------------
I want to get this kind of a reusult
------------------------------
|group_id | name |users_count|
------------------------------
| 10 |test1 | 3 |
| 11 |test2 | 2 |
| 12 |test3 | 0 |
------------------------------
You simply do this with the group by, as per the following bellow.
SELECT U.group_id ,U.RoleName,COUNT(R.Id)USERCOUNT
FROM usergroup U
LEFT OUTER JOIN usergroup_user R ON R.group_id =U.group_id
GROUP BY U.group_id ,U.RoleName
select
group_id,
name,
(select count(user_id) from [dbo].[usergroup_user] where usergroup_user.group_id=[usergroup].group_id ) AS users_count
from [dbo].[usergroup]
SELECT usergroup.group_id ,usergroup.name,COUNT(usergroup_user.id) as users_count
FROM usergroup
LEFT OUTER JOIN usergroup_user ON usergroup.group_id =usergroup_user.group_id
GROUP BY usergroup.group_id ,usergroup.name

How to print the students name in this query?

The concerned tables are as follows:
students(rollno, name, deptcode)
depts(deptcode, deptname)
course(crs_rollno, crs_name, marks)
The query is
Find the name and roll number of the students from each department who obtained
highest total marks in their own department.
Consider:
i) Courses of different department are different.
ii) All students of a particular department take same number and same courses.
Then only the query makes sense.
I wrote a successful query for displaying the maximum total marks by a student in each department.
select do.deptname, max(x.marks) from students so
inner join depts do
on do.deptcode=so.deptcode
inner join(
select s.name as name, d.deptname as deptname, sum(c.marks) as marks from students s
inner join crs_regd c
on s.rollno=c.crs_rollno
inner join depts d
on d.deptcode=s.deptcode
group by s.name,d.deptname) x
on x.name=so.name and x.deptname=do.deptname group by do.deptname;
But as mentioned I need to display the name as well. Accordingly if I include so.name in select list, I need to include it in group by clause and the output is as below:
Kendra Summers Computer Science 274
Stewart Robbins English 80
Cole Page Computer Science 250
Brian Steele English 83
expected output:
Kendra Summers Computer Science 274
Brian Steele English 83
Where is the problem?
I guess this can be easily achieved if you use window function -
select name, deptname, marks
from (select s.name as name, d.deptname as deptname, sum(c.marks) as marks,
row_number() over(partition by d.deptname order by sum(c.marks) desc) rn
from students s
inner join crs_regd c on s.rollno=c.crs_rollno
inner join depts d on d.deptcode=s.deptcode
group by s.name,d.deptname) x
where rn = 1;
To solve the problem with a readable query I had to define a couple of views:
total_marks: For each student the sum of their marks
create view total_marks as select s.deptcode, s.name, s.rollno, sum(c.marks) as total from course c, students s where s.rollno = c.crs_rollno group by s.rollno;
dept_max: For each department the highest total score by a single student of that department
create view dept_max as select deptcode, max(total) max_total from total_marks group by deptcode;
So I can get the desidered output with the query
select a.deptcode, a.rollno, a.name from total_marks a join dept_max b on a.deptcode = b.deptcode and a.total = b.max_total
If you don't want to use views you can replace their selects on the final query, which will result in this:
select a.deptcode, a.rollno, a.name
from
(select s.deptcode, s.name, s.rollno, sum(c.marks) as total from course c, students s where s.rollno = c.crs_rollno group by s.rollno) a
join (select deptcode, max(total) max_total from (select s.deptcode, s.name, s.rollno, sum(c.marks) as total from course c, students s where s.rollno = c.crs_rollno group by s.rollno) a_ group by deptcode) b
on a.deptcode = b.deptcode and a.total = b.max_total
Which I'm sure it is easily improvable in performance by someone more skilled then me...
If you (and anybody else) want to try it the way I did, here is the schema:
create table depts ( deptcode int primary key auto_increment, deptname varchar(20) );
create table students ( rollno int primary key auto_increment, name varchar(20) not null, deptcode int, foreign key (deptcode) references depts(deptcode) );
create table course ( crs_rollno int, crs_name varchar(20), marks int, foreign key (crs_rollno) references students(rollno) );
And here all the entries I inserted:
insert into depts (deptname) values ("Computer Science"),("Biology"),("Fine Arts");
insert into students (name,deptcode) values ("Turing",1),("Jobs",1),("Tanenbaum",1),("Darwin",2),("Mendel",2),("Bernard",2),("Picasso",3),("Monet",3),("Van Gogh",3);
insert into course (crs_rollno,crs_name,marks) values
(1,"Algorithms",25),(1,"Database",28),(1,"Programming",29),(1,"Calculus",30),
(2,"Algorithms",24),(2,"Database",22),(2,"Programming",28),(2,"Calculus",19),
(3,"Algorithms",21),(3,"Database",27),(3,"Programming",23),(3,"Calculus",26),
(4,"Zoology",22),(4,"Botanics",28),(4,"Chemistry",30),(4,"Anatomy",25),(4,"Pharmacology",27),
(5,"Zoology",29),(5,"Botanics",27),(5,"Chemistry",26),(5,"Anatomy",25),(5,"Pharmacology",24),
(6,"Zoology",18),(6,"Botanics",19),(6,"Chemistry",22),(6,"Anatomy",23),(6,"Pharmacology",24),
(7,"Sculpture",26),(7,"History",25),(7,"Painting",30),
(8,"Sculpture",29),(8,"History",24),(8,"Painting",30),
(9,"Sculpture",21),(9,"History",19),(9,"Painting",25) ;
Those inserts will load these data:
select * from depts;
+----------+------------------+
| deptcode | deptname |
+----------+------------------+
| 1 | Computer Science |
| 2 | Biology |
| 3 | Fine Arts |
+----------+------------------+
select * from students;
+--------+-----------+----------+
| rollno | name | deptcode |
+--------+-----------+----------+
| 1 | Turing | 1 |
| 2 | Jobs | 1 |
| 3 | Tanenbaum | 1 |
| 4 | Darwin | 2 |
| 5 | Mendel | 2 |
| 6 | Bernard | 2 |
| 7 | Picasso | 3 |
| 8 | Monet | 3 |
| 9 | Van Gogh | 3 |
+--------+-----------+----------+
select * from course;
+------------+--------------+-------+
| crs_rollno | crs_name | marks |
+------------+--------------+-------+
| 1 | Algorithms | 25 |
| 1 | Database | 28 |
| 1 | Programming | 29 |
| 1 | Calculus | 30 |
| 2 | Algorithms | 24 |
| 2 | Database | 22 |
| 2 | Programming | 28 |
| 2 | Calculus | 19 |
| 3 | Algorithms | 21 |
| 3 | Database | 27 |
| 3 | Programming | 23 |
| 3 | Calculus | 26 |
| 4 | Zoology | 22 |
| 4 | Botanics | 28 |
| 4 | Chemistry | 30 |
| 4 | Anatomy | 25 |
| 4 | Pharmacology | 27 |
| 5 | Zoology | 29 |
| 5 | Botanics | 27 |
| 5 | Chemistry | 26 |
| 5 | Anatomy | 25 |
| 5 | Pharmacology | 24 |
| 6 | Zoology | 18 |
| 6 | Botanics | 19 |
| 6 | Chemistry | 22 |
| 6 | Anatomy | 23 |
| 6 | Pharmacology | 24 |
| 7 | Sculpture | 26 |
| 7 | History | 25 |
| 7 | Painting | 30 |
| 8 | Sculpture | 29 |
| 8 | History | 24 |
| 8 | Painting | 30 |
| 9 | Sculpture | 21 |
| 9 | History | 19 |
| 9 | Painting | 25 |
+------------+--------------+-------+
I take chance to point out that this database is badly designed. This becomes evident with course table. For these reasons:
The name is singular
This table does not represent courses, but rather exams or scores
crs_name should be a foreign key referencing the primary key of another table (that would actually represent the courses)
There is no constrains to limit the marks to a range and to avoid a student to take twice the same exam
I find more logical to associate courses to departments, instead of student to departments (this way also would make these queries easier)
I tell you this because I understood you are learning from a book, so unless the book at one point says "this database is poorly designed", do not take this exercise as example to design your own!
Anyway, if you manually resolve the query with my data you will come to this results:
+----------+--------+---------+
| deptcode | rollno | name |
+----------+--------+---------+
| 1 | 1 | Turing |
| 2 | 6 | Bernard |
| 3 | 8 | Monet |
+----------+--------+---------+
As further reference, here the contents of the views I needed to define:
select * from total_marks;
+----------+-----------+--------+-------+
| deptcode | name | rollno | total |
+----------+-----------+--------+-------+
| 1 | Turing | 1 | 112 |
| 1 | Jobs | 2 | 93 |
| 1 | Tanenbaum | 3 | 97 |
| 2 | Darwin | 4 | 132 |
| 2 | Mendel | 5 | 131 |
| 2 | Bernard | 6 | 136 |
| 3 | Picasso | 7 | 81 |
| 3 | Monet | 8 | 83 |
| 3 | Van Gogh | 9 | 65 |
+----------+-----------+--------+-------+
select * from dept_max;
+----------+-----------+
| deptcode | max_total |
+----------+-----------+
| 1 | 112 |
| 2 | 136 |
| 3 | 83 |
+----------+-----------+
Hope I helped!
Try the following query
select a.name, b.deptname,c.marks
from students a
, crs_regd b
, depts c
where a.rollno = b.crs_rollno
and a.deptcode = c.deptcode
and(c.deptname,b.marks) in (select do.deptname, max(x.marks)
from students so
inner join depts do
on do.deptcode=so.deptcode
inner join (select s.name as name
, d.deptname as deptname
, sum(c.marks) as marks
from students s
inner join crs_regd c
on s.rollno=c.crs_rollno
inner join depts d
on d.deptcode=s.deptcode
group by s.name,d.deptname) x
on x.name=so.name
and x.deptname=do.deptname
group by do.deptname
)
Inner/Sub query will fetch the course name and max marks and the outer query gets the corresponding name of the student.
try and let know if you got the desired result
Dense_Rank() function would be helpful in this scenario:
SELECT subquery.*
FROM (SELECT Student_Total_Marks.rollno,
Student_Total_Marks.name,
Student_Total_Marks.deptcode, depts.deptname,
rank() over (partition by deptcode order by total_marks desc) Student_Rank
FROM (SELECT Stud.rollno,
Stud.name,
Stud.deptcode,
sum(course.marks) total_marks
FROM students stud inner join course course on stud.rollno = course.crs_rollno
GROUP BY stud.rollno,Stud.name,Stud.deptcode) Student_Total_Marks,
dept dept
WHERE Student_Total_Marks.deptcode = dept.deptname
GROUP BY Student_Total_Marks.deptcode) subquery
WHERE suquery.student_rank = 1

Want to JOIN fourth table in query

I have four tables:
mls_category
points_matrix
mls_entry
bonus_points
My first table (mls_category) is like below:
*--------------------------------*
| cat_no | store_id | cat_value |
*--------------------------------*
| 10 | 101 | 1 |
| 11 | 101 | 4 |
*--------------------------------*
My second table (points_matrix) is like below:
*----------------------------------------------------*
| pm_no | store_id | value_per_point | maxpoint |
*----------------------------------------------------*
| 1 | 101 | 1 | 10 |
| 2 | 101 | 2 | 50 |
| 3 | 101 | 3 | 80 |
*----------------------------------------------------*
My third table (mls_entry) is like below:
*-------------------------------------------*
| user_id | category | distance | status |
*-------------------------------------------*
| 1 | 10 | 20 | approved |
| 1 | 10 | 30 | approved |
| 1 | 11 | 40 | approved |
*-------------------------------------------*
My fourth table (bonus_points) is like below:
*--------------------------------------------*
| user_id | store_id | bonus_points | type |
*--------------------------------------------*
| 1 | 101 | 200 | fixed |
| 2 | 102 | 300 | fixed |
| 1 | 103 | 4 | per |
*--------------------------------------------*
Now, I want to add bonus points value into the sum of total distance according to the store_id, user_id and type.
I am using the following code to get total distance:
SELECT MIN(b.value_per_point) * d.total_distance FROM points_matrix b
JOIN
(
SELECT store_id, sum(t1.totald/c.cat_value) as total_distance FROM mls_category c
JOIN
(
SELECT SUM(distance) totald, user_id, category FROM mls_entry
WHERE user_id= 1 AND status = 'approved' GROUP BY user_id, category
) t1 ON c.cat_no = t1.category
) d ON b.store_id = d.store_id AND b.maxpoint >= d.total_distance
The above code is correct to calculate value, now I want to JOIN my fourth table.
This gives me sum (60*3 = 180) as total value. Now, I want (60+200)*3 = 780 for user 1 and store id 101 and value is fixed.
i think your query will be like below
SELECT Max(b.value_per_point)*( max(d.total_distance)+max(bonus_points)) FROM mls_point_matrix b
JOIN
(
SELECT store_id, sum(t1.totald/c.cat_value) as total_distance FROM mls_category c
JOIN
(
SELECT SUM(distance) totald, user_id, category FROM mls_entry
WHERE user_id= 1 AND status = 'approved' GROUP BY user_id, category
) t1 ON c.cat_no = t1.category group by store_id
) d ON b.store_id = d.store_id inner join bonus_points bp on bp.store_id=d.store_id
DEMO fiddle

Dynamic columns in sql Join condition

Customer
customer_id | customer_name | customer_city | customer_number
---------------------------------------------------------------
1 | john | sanjose | 978234
2 | chris | newyork | 293
3 | mary | madrid | 342943
4 | tom | bangkok | 8627093
---------------------------------------------------------------
Data
data_id | data_name | data_city | data_number | data_cust_id | customer_id
--------------------------------------------------------------------------------------------
1 | abc | xyz | 990 | 1 | NULL
2 | john | sanjose | 978234 | 1 | NULL
3 | mary | madrid | 8627093 | 3 | NULL
4 | tom | LA | 7729 | 4 | NULL
ActionType
action_id | action_description
-----------------------------------
1 | customer_name
2 | customer_number
3 | customer_city
DataToAction
id | data_id | action_id
--------------------------
1 | 1 | 1
2 | 1 | 2
4 | 2 | 1
5 | 2 | 2
6 | 2 | 3
7 | 3 | 1
8 | 3 | 2
9 | 4 | 1
There are 4 tables -
Customer - Has customer datails
Data - Raw data pulled from an external source (has customer data and others)
ActionType - Has the column names which will be used in a join condition
DataToAction - For each of the raw data row in Data table, the columns to be used in the join is specified here.
Objective - To populate customer_id in 'Data' table.
I need something like this
UPDATE D
SET D.customer_id = C.customer_id
FROM Data D
INNER JOIN Customer C on D.data_cust_id = C.customer_id
WHERE *("GET THE COLUMNS TO BE MATCHED FROM DATATOACTION TABLE AND USE HERE")*
For eg., for Data id 1, i will update customer_id based on customer_name & customer_number, for data id 2 i will udpate customer_id based on customer_name, customer_number & customer_city and so on.
How do I apply the dynamic column conditions in the where clause for each of the row wherein the columns to be matched are specified in a different table.
Well the question is quite unclear. Can u elaborate the final resulset.
Purpose of ActionType table??
UPDATE D
SET D.customer_id = C.customer_id
FROM Data D
INNER JOIN Customer C on D.data_cust_id = C.customer_id
INNER JOIN DataToAction DA ON DA.data_id = D.data_id

sql compact 3.5, select top n rows from each group

I am writing a query to select the top 1 record from each group. Keep in mind that I working on sql compact 3.5 and thus can not use the rank function. I'm pretty sure my query is incorrect but I'm not sure how to select top from each group. Any one got any ideas?
Here is the query I was trying to get working
/*
* added fH.InvoiceNumber to my query to get result further below.
/
select tH., t.CustomerNumber, c.CustomerName, fH.Status, fH.InvoiceNumber
from tenderHeader tH
join task t ON tH.TaskActivityID = t.ActivityID
join finalizeTicketHeader fH ON tH.FinalizeTicketTaskActivityID = fH.TaskActivityID
join customer c ON t.CustomerNumber = c.CustomerNumber
where fH.Status <> '3' AND t.TripID = '08ea6982-6efd-46fa-9753-0fd8b076f24c';
Here is what my tables look like:
customer table:
|------------------------------------------------|
| CustomerNumber | CustomerName | Address1 | ... |
|------------------------------------------------|
| 0012084737 | Customer A | 150 Rd A | ... |
|------------------------------------------------|
| 0012301891 | Customer B | 152 Rd A | ... |
|------------------------------------------------|
task table
|-----------------------------------------------------------------|
| ActivityID | TripID | TaskTypeName | Status | CustomerNumber |
|-----------------------------------------------------------------|
| 4967f6cc | 08ea6982 | Payment | 2 | 0012084737 |
|-----------------------------------------------------------------|
| e96469a1 | 08ea6982 | Payment | 2 | 0012301891 |
|-----------------------------------------------------------------|
finalizeTicketHeader table
|---------------------------------------------------|
| TaskActivityID | InvoiceNumber | Amount | Status |
|---------------------------------------------------|
| 916082c8 | 1000 | 563.32 | 3 |
|---------------------------------------------------|
| 916082c8 | 1001 | -343.68 | 0 |
|---------------------------------------------------|
| 4b38bf60 | 1002 | 152.29 | 0 |
|---------------------------------------------------|
| 4b38bf60 | 1003 | -35.80 | 0 |
|---------------------------------------------------|
tenderHeader table
|-------------------------------------------------------------------------------------|
| TaskActivityID | InvoiceNumber | PastDue | TodaysDue | FinalizeTicketTaskActivityID |
|-------------------------------------------------------------------------------------|
| 4967f6cc | 1234567891 | 23.55 | 219.64 | 916082c8 |
|-------------------------------------------------------------------------------------|
| e96469a1 | 1234567893 | 0.00 | 116.49 | 4b38bf60 |
|-------------------------------------------------------------------------------------|
the problem I was having was getting duplicates.
like so:
|------------------------------------------------------------------------------------------------------------------------------------|
| TaskActivityID | InvoiceNumber | PastDue | TodaysDue | FinalizeTicketTaskActivityID | CustomerNumber | CustomerName | InvoiceNumber |
|------------------------------------------------------------------------------------------------------------------------------------|
| 4967f6cc | 1234567891 | 23.55 | 219.64 | 916082c8 | 0012084737 | Customer A | 1001 |
|------------------------------------------------------------------------------------------------------------------------------------|
| e96469a1 | 1234567893 | 0.00 | 116.49 | 4b38bf60 | 0012301891 | Customer B | 1002 |
|------------------------------------------------------------------------------------------------------------------------------------|
| e96469a1 | 1234567893 | 0.00 | 116.49 | 4b38bf60 | 0012301891 | Customer B | 1003 |
|------------------------------------------------------------------------------------------------------------------------------------|
I've rewritten the query like so, but I need to get specific columns from the sub query.
select tH.* from tenderHeader th
inner join task t on tH.TaskActivityID = t.ActivityID
inner join (
select k.TaskActivityID from finalizeTicketHeader k group by k.TaskActivityID
) as fH on tH.FinalizeTicketTaskActivityID = fH.TaskActivityID
inner join customer c on t.CustomerNumber = c.CustomerNumber
I need to get the status from fH. Any ideas of how to do that?
select tH.*, fH.Status from tenderHeader th
inner join task t on tH.TaskActivityID = t.ActivityID
inner join finalizeTicketHeader fH on tH.FinalizeTicketTaskActivityID = tH.TaskActivityID
inner join customer c on t.CustomerNumber = c.CustomerNumber
where tH.FinalizeTicketTaskActivityID = (
select top (1) k.TaskActivityID from finalizeTicketHeader k
);
but it seems that sql compact 3.5 does not support scalar values with subquery in where cause.
Here is an example that demonstrat a way of selecting the top 1 from each group
id|time
--------
2 | 1:10
2 | 0:45
2 | 1:45
2 | 1:30
1 | 1:00
1 | 1:10
the table is called table_1; we group by id and assume that time should be desc ordered
select table_1.* from table_1
inner join (
select id, max(time) as max_time from table_1
group by id
) as t
on t.max_time = table_1.time and table_1.id = t.id
order by table_1.id
the result we get is
id|time
--------
1 | 1:10
2 | 1:45