Implementing ORDER BY clause in c++

I

Index

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.
 
J

Jerry Coffin

@i40g2000cwc.googlegroups.com>,
(e-mail address removed) 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.
 
I

Index

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.
 
J

Jerry Coffin

@y43g2000cwc.googlegroups.com>,
(e-mail address removed) 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);
 
I

Index

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.
 
I

Ian Collins

Index said:
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.
 
J

Jerry Coffin

@j73g2000cwa.googlegroups.com>,
(e-mail address removed) 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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top