简体   繁体   中英

use one table as a rule while performing select query on the other table

I have a table name test

first       last
raj         kumar
raj        patel

there is hundreds of row in this table.

I have another table called class having all the names that are present in the test table and its marks for each subject.

class_id    first_name   last_name   subject     marks
 1       raj           kumar       physics    70
 1       raj           kumar       chemistry  70
 1       raj           patel       physics    80
 1       raj           kumar       math       90
 1       raj           kumar       computer   80
 1       raj           patel       chemistry  90
 1       raj           patel       math       100
 2       raj           kumar       physics    70
 2       raj           kumar       chemistry  70
 2       raj           patel       physics    80
 2       raj           kumar       math       90
 2       raj           kumar       computer   80
 2       raj           patel       chemistry  90
 2       raj           patel       math       100

Now i want to know the total marks of each student present in the test table in below format :.

class_id    raj.kumar    raj.patel
 1          310           270
 2           n             m

So there will be n number of columns in the resulting tbale

for this particular case we can write

 select class_id
    sum(case when first_name = 'raj' and last_name = 'Kumar' then marks else 0) as "raj.kumar",
    sum(case when first_name = 'raj' and last_name = 'patel' then marks else 0)as "raj.patel"
    from class 
    group by class_id

Since number of students is not fixed which is present in the test table. so i don't want to hardcode the first and last name in my query. I want something like this which could be able to calculate marks for all the students which are present on test table.

 select class_id, 
    for(i = 0; i < test.size; i++)
     sum(case when first_name = i.first and last_name = i.last then marks else 0 ) as i.first|| '.' ||i.last,
    from class
    group class_id

How to write query or stored procedure for this thanks in advance.

I am using postgresql.

For all students?

What is wrong with:

select class_id, first_name, last_name, sum(marks)
  from class
group by class_id, first_name, last_name;

So you want a crosstab. Here the main problem is that the planner needs to know how many columns and what their types are before starting. So the bad news is there is no direct way to do this.

So you have a few options:

  1. look at the tablefunc extension and dynamically generate your query around the crosstab() function
  2. Use xml or json types and return objects or documents rather than records.
  3. Use my query above and a client-side tool like excel to do the crosstab for you.
  4. (edit) You can dynamically generate SQL in a stored procedure, and return a refcursor, but that brings you back to the problems just moving your "client" code generation into a function.

EDIT To be clear your problem is a planner limitation. You cannot have expand a column list into a variable number of columns. So you have to generate the SQL from outside the db. You cannot handle a dynamic number of columns directly in SQL.

Now, I would highly recommend using the crosstab() function from the tablefunc extension because this simplifies conceptually the result quite a bit. If you have to do this manually (please don't) you can write a query generator in pl/perl or pl/pgsql by selecting from the other table, and then use pl/pgsql's EXECUTE into a cursor. You can then return a refcursor. This is not ideal because the client then has to FETCH from the returned refcursor.

So your first point is to decide on where you are going to generate the SQL code that will run. Will this be in a database client? Or in dynamic SQL (with a requirement that the client FETCH rows separately from running the function)?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM