Implementing ORDER BY clause in c++

Discussion in 'C++' started by Index, May 27, 2006.

  1. Index

    Index Guest

    Hi,
    I have a file which I want to sort depending on multiple columns.
    Actually I want to implement the following query through programming:

    SELECT SUM(VALUES) GROUP BY x,y ORDER BY x,y;

    the aggregation is complete.What I want is to order the result.I have 7
    fields which are used in GROUP BY clause and I need to ORDER them with
    those fields.
    Any help will be highly appreciated.
     
    Index, May 27, 2006
    #1
    1. Advertising

  2. Index

    Jerry Coffin Guest

    In article <1148688653.857714.89540
    @i40g2000cwc.googlegroups.com>,
    says...
    > Hi,
    > I have a file which I want to sort depending on multiple columns.
    > Actually I want to implement the following query through programming:
    >
    > SELECT SUM(VALUES) GROUP BY x,y ORDER BY x,y;
    >
    > the aggregation is complete.What I want is to order the result.I have 7
    > fields which are used in GROUP BY clause and I need to ORDER them with
    > those fields.


    You need to create a comparison function/functor that
    does a comparison based on those fields. It's difficult
    to say with certainty how to do that without knowing the
    types of x and y, but with typical types, it'd be
    something on the order of:

    struct whatever {
    int x, y;

    bool operator<(whatever const &other) {
    return x < other.x || y < other.y;
    }
    };

    Then you can use std::sort (or stable_sort, etc.) to sort
    the items using that ordering.

    Alternatively, since you're creating the results of the
    group by clause, you might prefer to create those results
    in an std::set (or perhaps std::map), in which case
    they'll be sorted automatically. For this to work, you
    still need to define operator< for the type, or else
    create a similar comparison function, but as a free
    function or functor, and then tell the std::set/map to
    use that for its comparisons.

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
     
    Jerry Coffin, May 27, 2006
    #2
    1. Advertising

  3. Index

    Index Guest

    Hi,
    Thanks for all the inputs.But what I understand from all this that at
    any instant, the std:sort uses only one key to sort.But I need multiple
    key sorting for each instant where ther combination of teh keys is
    dynamic.Algorithmically, i devised something like this, but i don't
    think it is efficient.Can I use any STL method to achieve the same?

    say for a record in a vector, two keys x and y are to be used to sort
    the file where the file has been already aggregated using A and then
    B.[same as SELECT SUM(VALUES) GROUP BY x,y]...I already implemented
    this portion.Now I need to ORDER them by x and then by y.I thought of
    implementing the order by as follows:

    First sort by x;
    Then sort by y depending on the folllowing condition while swapping the
    elements:
    if (Vector->x == Vector[i+1]->x && Vector->y > Vector[i+1]->y)
    {
    SWAP (Vector <-> Vector[i+1]);

    }

    Now I have 5 columns which can be the keys in various combination an
    dthe sorting should be done accordingly.There will be five different
    sorting.

    say for 3 keys x,y and z, it will be as follows:
    First sort by x;
    Then sort by y depending on the folllowing condition while swapping the
    elements:
    if (Vector->x == Vector[i+1]->x && Vector->y > Vector[i+1]->y)
    {
    SWAP (Vector <-> Vector[i+1]);
    }

    Then sort by z depending on the folllowing condition while swapping the
    elements:
    if (Vector->x == Vector[i+1]->x && Vector->y == Vector[i+1]->y &&
    Vector->z > Vector[i+1]->z)
    {
    SWAP (Vector <-> Vector[i+1]);

    }

    I am really not very convinced this is a very good idea and I think
    there can be better ways to do so.
    Please do let me know of any idea.
    Thanks.
     
    Index, May 29, 2006
    #3
  4. Index

    Jerry Coffin Guest

    In article <1148857630.230937.24620
    @y43g2000cwc.googlegroups.com>,
    says...
    > Hi,
    > Thanks for all the inputs.But what I understand from all this that at
    > any instant, the std:sort uses only one key to sort.


    std::sort uses whatever result is returned by operator<
    (or the specified functor) to determine the order. That
    can be based on as many fields as you prefer.

    All you have to define is the relative ordering of any
    two keys and encode that into your comparison function.
    std::sort can handle things from there.

    For example:

    struct data {
    int x, y, z;

    bool operator<(data const &other) {
    if (x<other.x)
    return true;
    if (x>other.x)
    return false;

    // x == other.x, check y
    if (y<other.y)
    return true;
    if (y>other.y)
    return false;

    // x==other.x, y==other.y, check z
    if (z<other.z)
    return true;
    return false;
    }
    }

    Now, std::sort(some_data.begin(), some_data.end())
    produces the same ordering as 'order by x, y, z' would in
    SQL -- order primarily by x, and if the x's are equal
    order by y, and if the y's are equal, order by z.

    If you need the equivalent of different order by clauses,
    you have to write up each one, and specify the correct
    one when you call std::sort:

    // define the ordering.
    struct by_yz {
    bool operator()(data const &a, data const &b) {
    if (a.y<b.y)
    return true;
    if (a.y>b.y)
    return false;
    if (a.z<b.z)
    return true;
    return false;
    }
    };

    // sort data equivalent to 'order by y, z' in SQL:
    std::sort(some_data.begin(), some_data.end(), by_yz);

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
     
    Jerry Coffin, May 29, 2006
    #4
  5. Index

    Index Guest

    Hi,
    Thanks. I have one more question, if x,y and z are of different data
    types, say two are strings and one int, how should I define the
    operator to handle different data types?Since there are five such
    fields on which teh ordering is to be done, i am planning to define
    just five functions depending on the number of parameters and not on
    specific types [otherwise i need to have all possible
    combinations!!!!].How can I make the operator able to handle both
    string as well as integer?

    Thanks.
     
    Index, May 29, 2006
    #5
  6. Index

    Ian Collins Guest

    Index wrote:
    > Hi,
    > Thanks. I have one more question, if x,y and z are of different data
    > types, say two are strings and one int, how should I define the
    > operator to handle different data types?Since there are five such
    > fields on which teh ordering is to be done, i am planning to define
    > just five functions depending on the number of parameters and not on
    > specific types [otherwise i need to have all possible
    > combinations!!!!].How can I make the operator able to handle both
    > string as well as integer?
    >

    Please quote the context of what you are replying to a a courtesy to
    people who don't use google. See <http://cfaj.freeshell.org/google/>

    To answer the question, as along as all the types you use have a <
    operator defined, just use the struct < operator suggested on this or
    your other thread.

    --
    Ian Collins.
     
    Ian Collins, May 29, 2006
    #6
  7. Index

    Jerry Coffin Guest

    In article <1148923676.902724.75750
    @j73g2000cwa.googlegroups.com>,
    says...
    > Hi,
    > Thanks. I have one more question, if x,y and z are of different data
    > types, say two are strings and one int, how should I define the
    > operator to handle different data types?


    As long as all the data types support the < operator,
    it's irrelevant.

    > Since there are five such
    > fields on which teh ordering is to be done, i am planning to define
    > just five functions depending on the number of parameters and not on
    > specific types [otherwise i need to have all possible
    > combinations!!!!].How can I make the operator able to handle both
    > string as well as integer?


    As long as you always use the fields in the same order,
    you can pretty easily get by with only one comparison
    functor, and specify the fields to be used when you
    construct the comparison object:

    // for the moment, I'll only do three fields, but each
    // of a different type.
    struct record {
    int x;
    std::string y;
    long z;
    };

    struct order {

    // each of these must be a power of 2
    enum { by_x = 1, by_y = 2, by_z = 4};
    int fields_;

    order(int fields) : fields_(fields) {}

    bool operator()(record const &a, record const &b)
    {
    if (fields_ & by_x) {
    if (a.x < b.x)
    return true;
    else if (a.x > b.x)
    return false;
    }
    if (fields_ & by_y) {
    // compare by field y
    }
    if (fields_ & by_z) {
    // compare by field z
    }
    }
    };

    To use this, you'd specify the fields to sort on when you
    construct your comparison object. For example, to compare
    based on fields x and z, you'd specify:

    std::sort(records.begin(), records.end(),
    order(order::by_x | order::by_z));

    Arguably, using '&' to connect the field specifiers would
    make look more sensible. If you don't mind a little
    ugliness inside the class, it's pretty easy to support
    that as well -- you just need to invert the sense of
    everything:

    struct order {

    enum {
    by_x = (-1 & ~1),
    by_y = (-1 & ~2),
    by_z = (-1 & ~4)
    };
    int fields_;

    order(int fields) : fields_(fields) {}

    bool operator()(record const &a, record const &b) {
    if (!(fields_ & by_x)) {
    if (a.x < b.x)
    return true;
    if (a.x > b.x)
    return false;
    }
    if (!(fields_ & by_y)) {
    if (a.y < b.y)
    return true;
    if (a.y > b.y)
    return false;
    }
    if (!(fields_ & by_z)) {
    if (a.z < b.z)
    return true;
    if (a.z > b.z)
    return true;
    }
    return false;
    }
    };


    then the sort would look like this:

    std::sort(records.begin(), records.end(),
    order(order::by_x & order::by_z));

    It's probably open to argument whether this is really
    even syntactic sugar, or really syntactic saccharin.

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
     
    Jerry Coffin, Jun 1, 2006
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Smith John

    Order by Clause....

    Smith John, Dec 7, 2004, in forum: ASP .Net
    Replies:
    7
    Views:
    523
    John Smith
    Dec 7, 2004
  2. Soren Kuula
    Replies:
    2
    Views:
    541
    Soren Kuula
    Feb 1, 2004
  3. cspoh
    Replies:
    0
    Views:
    267
    cspoh
    Jul 31, 2003
  4. Peroq

    Trouble with ORDER BY clause

    Peroq, Oct 23, 2003, in forum: ASP General
    Replies:
    15
    Views:
    248
    Peroq
    Oct 23, 2003
  5. Stephan Kämper
    Replies:
    2
    Views:
    257
    Stephan Kämper
    Jan 18, 2004
Loading...

Share This Page