Skip navigation
Currently Being Moderated

distinct on more than one field

Feb 14, 2008 2:51 PM

I have a table that has two fields in there, let's say field1 and field2.

I need to somehow join these together to get a distinct list of records from each, as if they were one, so for example
field1,field2
1,10
1,12
4,1
6,1

If I query WHERE field1=1 or field2=1

I need to get one one result 10,12,4,6 which gives me all the records relating to record 1 regardless of the order

Can anybody help me with this?

Thanks

Mark
 
Replies
  • Currently Being Moderated
    Feb 14, 2008 3:07 PM   in reply to ACS LLC
    Use2 UNION queries and a loop.
    Both unions will give you distinct results.

    query_1
    Select field1 as x
    from mytable
    UNION
    Select field2
    from mytable

    query_2
    Select field1
    from mytable
    where field2 = #query_1.x#
    UNION
    Select field2
    from mytable
    where field1 = #query_1.x#

     
    |
    Mark as:
  • Currently Being Moderated
    Feb 14, 2008 5:35 PM   in reply to ACS LLC
    Try a case statement

    SELECT DISTINCT CASE WHEN field1 = 1 THEN field2 ELSE field1 END AS FieldValue
    FROM TheTable
    WHERE Field1 = 1 OR Field2 = 1
     
    |
    Mark as:
  • Currently Being Moderated
    Feb 14, 2008 6:48 PM   in reply to ACS LLC
    quote:

    Originally posted by: ACS LLC
    I have a table that has two fields in there, let's say field1 and field2.

    I need to somehow join these together to get a distinct list of records from each, as if they were one, so for example
    field1,field2
    1,10
    1,12
    4,1
    6,1

    If I query WHERE field1=1 or field2=1

    I need to get one one result 10,12,4,6 which gives me all the records relating to record 1 regardless of the order

    Can anybody help me with this?

    Thanks

    Mark

    What is your db? If you are using one that allows you to select by row number, you are in luck. Or, if you know the 1st row has the lowest value of field 1, that also makes it pretty simple.
     
    |
    Mark as:
  • Currently Being Moderated
    Feb 14, 2008 9:44 PM   in reply to ACS LLC
    Did you try using CASE? Is order important?
     
    |
    Mark as:
  • Currently Being Moderated
    Feb 15, 2008 7:27 AM   in reply to -==cfSearching==-
    How about something like this?

    SELECT DISTINCT either_field
    FROM
    (SELECT field1 AS either_field
    FROM yourtable
    WHERE field1=1 OR field2=1
    UNION
    SELECT field2 AS either_field
    FROM yourtable
    WHERE field1=1 OR field2=1) AS tbl
    ORDER BY either_field

    Phil
     
    |
    Mark as:
  • Currently Being Moderated
    Feb 15, 2008 9:15 AM   in reply to paross1
    I think field1=1 or field2=1 was just an example. He needs ALL unique values of both fields with any value of the other field not just 1. So it could be mine or Paross solution with addition of dinamic value passed as variable or result of other query.
     
    |
    Mark as:
  • Currently Being Moderated
    Feb 15, 2008 10:01 AM   in reply to ACS LLC
    quote:

    .....where I store a list of comma delim' numbers in one field
    Oooooh, VERY bad idea..... very BAD design. By denormalizing your data, you are asking for many more problems than you think that you are solving.

    Phil
     
    |
    Mark as:
  • Currently Being Moderated
    Feb 15, 2008 10:30 AM   in reply to ACS LLC
    It is hard to comment on what you are doing because you gave an incomplete picture of what you were trying to do, and only asked for a narrow example. Judging from your last statement, I have a hunch that you may have a data model problem that may be helped by proper normalization, but it is hard to say without more specific information on your current design, and description of what you are really trying to accomplish (not how you think that you may accomplish it).

    Phil
     
    |
    Mark as:
  • Currently Being Moderated
    Feb 15, 2008 10:35 AM   in reply to ACS LLC
    Are you talking about a many-to-many relationship between members and friends? Are both (members and friends) listed in the "members" table? Are you trying to do something like being able to list all of the friends of a particular member, etc.?

    Phil
     
    |
    Mark as:
  • Currently Being Moderated
    Feb 15, 2008 10:51 AM   in reply to ACS LLC
    Very simple fix. You need what is called an "associative entity" which is a fancy name for a link table between "members" and "friends" in order to resolve the many-to-many relationship. Because "friends" are also "members", then the link to the member table will be essentially self referential.

    Lets say you have a member table, and you wish to link to other members as friends, then you could create a table named friends with member_id and friend_id feilds. Both the member_id and friend_id fields are foreign keys back to the member table member_id field, but each row in the friends table would contain the member_id of the member, and the friend_id (member_id) of the friend.

    Lets say that you have Joe, and his member_id is 1, and his friends are Fred (member_id = 2) and Mary (member_id 3). You would have two rows in the friends table, each would have a member_id value of 1, but different friend_id values (2 and 3 respectively). In order to find out who Joe's friends were, you could write a query like this:

    SELECT m1.name AS member,
    m2.name AS friend
    FROM member m1
    INNER JOIN friend f ON m1.member_id = f.member_id
    INNER JOIN member m2 ON f.friend_id = m2.member_id
    WHERE m1.name = 'Joe'

    ...or something similar

    Phil
     
    |
    Mark as:
  • Currently Being Moderated
    Feb 15, 2008 11:58 AM   in reply to ACS LLC
    quote:

    Originally posted by: ACS LLC
    Really?

    I only ever have to search by the unique UID of the user, so if I need the record for user 123 I just search on the user record for user_uid=123 and I retrieve the list, I will never have to search through the list in SQL, just get the data

    My concern on top of the complex code is that if I have let's say 200,000 members, and each one has an average of say 25 'friends', that's 5,000,000 records... and I actually anticipate a LOT more with potentially higher averages per person... I'm relucant to have a query gather a record set from a list that could span 10-20M or more records for multiple users at the same time... could get ugly.

    I could always 'undo' the work I've done as we grow, but I can't see any problems with the way I'm doing it...yet! ;-)

    Paross was right. Everything you mention describes a simple many to many relationship. For all I know, that's what you had when you wrote the original post.

    Lots of records are no big deal. If you have that much data it will easier and quicker to get than it from a normalized schema than from varchar fields containing list.

    In fact, paross's answer timestamped 02/15/2008 03:27:06 PM is the best one on this thread.
     
    |
    Mark as:
  • Currently Being Moderated
    Feb 15, 2008 12:17 PM   in reply to ACS LLC
    Since your "link" table is essentially the only one that is really going to have the large number of rows, and since it would be comprised of two ID fields that could/should be easily indexed, you really shouldn't experience a significant performance hit unless you are doing something much more complex in your queries. I can not see any other method that would not be worse in regards to performance, and certainly not better in regards to simplified code.

    Phil
     
    |
    Mark as:
  • Currently Being Moderated
    Feb 15, 2008 2:32 PM   in reply to ACS LLC
    quote:

    Originally posted by: ACS LLC
    I pretty much understand his solution, it is more or less the same as my first approach. But the huge amount of records that I could create is still of concern to me.

    The largest set of records I've ever handled was around 26M, at this point even with indexing in the right places it started to slow down. This site could have similar amounts but more hits.

    What sort of problems do you forsee if I do it the other way with one record and a comma delim' list? note that I won't search that list only the uid of the person (member) that I need to refer to


    Your sql will be
    where field1 = 1
    or field2 like '1,%'
    or field2 like '%,1,%'
    or field2 like '%,1'

    Put in a few thousand records and see how fast that one is. And bear in mind, this is only step one. You still have to loop through all the lists to get the ids, and then run another query to get the names.
     
    |
    Mark as:
  • Currently Being Moderated
    Feb 15, 2008 2:38 PM   in reply to Dan Bracuk
    quote:

    Originally posted by: Dan Bracuk
    Put in a few thousand records and see how fast that one is.



    Yes, that has to be one of the worst performing options. Forget about any utilization of indexes. Not to mention increased data integrity problems.
     
    |
    Mark as:
  • Currently Being Moderated
    Feb 16, 2008 1:33 PM   in reply to ACS LLC
    For freinds? The simplest way is:

    table person
    person_id
    name
    more stuff

    table freind (this is the many to many one)
    person_id
    freind_id.

    To get all the freinds of id=1, do a union query. The top half gets person 1's freinds and the bottom half gets people who have person 1 has a freind.

    select p.person_id id, name
    from person p join freind f on p.person_id = f.freind_id
    where p.person_id = 1
    union
    select p.person_id id, name
    from person p join freind f on p.person_id = f.person_id
    where freind_id = 1

    For the freind table, your primary key is both fields. Also, each field is a foreign key to person.
     
    |
    Mark as:
  • Currently Being Moderated
    Feb 16, 2008 1:55 PM   in reply to ACS LLC
    The difference between my freinds table and yours is the primary key. You have a single field, independant of the two others, I have the two fields. My method prevents double entries, yours allows it.

    As far as whether 13 and 52 are mutual freinds if one befreinds the other, that is not a coding question. That's a business rule.
     
    |
    Mark as:
  • Currently Being Moderated
    Feb 16, 2008 2:25 PM   in reply to ACS LLC
    If your rules are that people become mutual freinds when one befreinds the other, then you want two records.

    About primary keys, what I wrote is different than what you seem to be referring to in your most recent post.
     
    |
    Mark as:
  • Currently Being Moderated
    Feb 16, 2008 3:06 PM   in reply to ACS LLC
    If you are able to insert duplicate records then you deviated from my suggestion. But it's your app, not mine.
     
    |
    Mark as:
  • Currently Being Moderated
    Feb 16, 2008 3:46 PM   in reply to ACS LLC
    Take at least a one hour break. Then read everything I wrote on this thread today. It's there.

    By the way, your plan to insert pairs of records for each freindship has a downside. You won't be able to tell anyone all the freinds they have selected or all the people who have chosen him. As long as you never ever have requirements like that, you'll be fine.
     
    |
    Mark as:
  • Currently Being Moderated
    Feb 18, 2008 7:17 AM   in reply to Dan Bracuk
    Both user_uid and friend_user_uid are foreign keys. You could make user_uid and friend_user_uid together as a composite primary key, or enable a UNIQUE database constraint on BOTH fields together, so that both fields combined have to be unique, but not either separately.

    Phil
     
    |
    Mark as:
  • Currently Being Moderated
    Feb 18, 2008 8:50 AM   in reply to ACS LLC
    Of course, creating a UNIQUE database constraint will prevent you from adding duplicate entries to the database, and will raise a database exception if you try, so your "application" (CF) code should also be preventing this, or at least, handle the database exception. The constraint "protects" the integrity of the database, but your ColdFusion code should also "protect" the application from throwing unhandled exceptions.

    Phil
     
    |
    Mark as:

More Like This

  • Retrieving data ...

Bookmarked By (0)

Answers + Points = Status

  • 10 points awarded for Correct Answers
  • 5 points awarded for Helpful Answers
  • 10,000+ points
  • 1,001-10,000 points
  • 501-1,000 points
  • 5-500 points