Problems with Facebook fql.query - sql

I have some problems with this fql.query method:
select music
from user
where uid = ......
and music in (select music
from user
where uid = ......
)
I want to obtain common music interest between two users; it works with queries like this
select uid
from user
where uid = ......
and uid in (select uid
from user
where uid = ......
)
I think the problem is that the second query returns an integer and the first one returns a string array. Can anyone help me with this?
(Excuse my bad English! I'm from Spain ;) )

Does not the first query already gives you your answer?
I mean it does the following :
-- Display only music field
select music
from user
where uid = <first_USER> -- Selection of your first user
and music in ( -- We want to macth the string with another
select music -- Selects only the music field
from user
where uid = <second_USER> -- Selection of your second user
)
So you gets a music name that match in two user records.
Your second query seems a bit odd to me :
select uid
from user
where uid = <first_USER?>
and uid in (select uid
from user
where uid = <second_USER?>
)
Which basically translates to find the user_id matching user one and user two. Thing that does never happen since each user has it's own uid.
By the way, I don't know how facebook handles music string, but it may appear that user don't write their favorite music name in a common spelling and/or format. That may impede your matching system.

I tried this:
select music
from user
where uid=UID1
AND music IN (SELECT music from user where uid=UID2)
And it works fine when the UID1 music string matches exactly the UID2's one.

Related

Rails Select one random listings for premium users

In my rails app, I have Users and Listings. The Listings belong to a User. Listing has user_id and its filled with users id who is creating the listing.
A user can be a premium user, gold user or silver user.
What I want is for each premium user, select one random listing to show in premium listings.
I can do it in O(n**2) time or n+1 query as follow:
users_id = User.where(:role => "premium").pluck[:id]
final_array = Array.new
users_id.each do |id|
final_array << Listing.where(:user_id => id).sample(1)
end
final_array
Is there a better way of doing this?
You could try this:
listings = Listing.select(
<<~SQL
DISTINCT ON (users.id) users.id,
listings.*,
row_number() OVER (PARTITION BY users.id ORDER BY random())
SQL
)
.joins(:user)
.includes(:user)
.where(users: { role: :premium })
It gives a random Listing for every premium user.
It produces the only request to db and also it won't make an extra request for getting listing's user, so you are free to do something like this:
listings.each do |listing|
p listing.user
end
random_user_listings = []
User.includes(:listings).where(role: "premium").find_each do |user|
random_user_listings << user.listings.sample(1)
end
random_user_listings
To avoid N+1 query you need to combine them, perform query one time like this:
list = Listing.includes(:user).where(:role => "premium").sample(1)
Feel free to deal with list instead of Listing. Because now you're dealing with variable, not Query.
ids = list.pluck(:user_id).uniq
Getting array of ids like above and doing further steps as you did (but with list, not Listing)
Need to be noticed that, when you deal with Model you're dealing with QUERY. Avoiding doing that in loop statement.

OrientDB Select on two related vertex

I have a scenario as shown below ,
I want to query the database so I get the following result,
User Resource Permissions
Edi Plan A [view]
Where
resource.name = 'Plan A' and user.name = 'Edi'
my query for above is
SELECT name,
out('hasARole').out('ofType').in('isOfType')[name = 'Plan A'].name,
set(out('hasARole').out('hasA').name) as permission
FROM user
WHERE name = 'Edi'
It should display
User Resource Permissions
Adrian Plan A [view,edit, delete]
if I change it to,
Where
resource.name = 'Plan A' and user.name = 'Adrian'
my query for above is
SELECT name,
out('hasARole').out('ofType').in('isOfType')[name = 'Plan A'].name,
set(out('hasARole').out('hasA').name) as permission
FROM user
WHERE name = 'Adrian'
Now above queries work as long as the users don't have another role on another type of resource. e.g. if Edi had Admin role on let's say a resource type of Workspace then the query gives me back all the permissions that an Admin would have , instead of just view as he only has view permission on Plan A
I have used the following graph for my answer. Note that I have corrected some incositencies with your original edges.
I see a number of possible queries for this problem. I am a bit confused why you would want to return the User and Resource in the query, as you probably already have these records due to the fact you use them to create the query. You can't 'nest' the full records in the results either (unless you JSON them). Further to this, querying on the name field, and returning only the name field seem a little nonsensical to me - but maybe you have done so to simplify the question. Regardless, the following queries will get you on your way to your desired results.
My first idea is to run a query to get all of the Roles related to a Resource. We then run a query over these results to filter for the Roles that include the User. This looks like the following;
select from (
select expand(out('isOfType').in('ofType')) from Resource where name = "Plan A"
) where in('hasARole') contains first((select from User where name = "Edi"))
This query correctly returns just the Viewer record for both Edi and Adrian.
My second idea is to run 1 query for the Roles related to a Resource (similar to above), and another for the Roles related to a User, and then find the intersect. This looks like the following, and gives the same results as the query above;
select expand(intersect) from (
select intersect($resource_roles, $user_roles)
let
$resource_roles = (select expand(out('isOfType').in('ofType')) from Resource where name = "Plan A"),
$user_roles = (select expand(out('hasARole')) from User where name = "Edi")
)
Now if you really do want the User, Resource and Permissions all in the 1 result, you can use the following, or a variant of;
select first($user).name as User, first($resource).name as Resource, intersect(resource_roles, user_roles).name as Permissions from (
select $resource.out('isOfType').in('ofType') as resource_roles, $user.out('hasARole') as user_roles
let
$resource = (select from Resource where name = "Plan A"),
$user = (select from User where name = "Edi")
)
or
select first($user).name as User, first($resource).name as Resource, intersect($resource_roles, $user_roles).name as Permissions
let
$resource = (select from Resource where name = "Plan A"),
$resource_roles = (select expand(out('isOfType').in('ofType')) from $parent.$resource),
$user = (select from User where name = "Edi"),
$user_roles = (select expand(out('hasARole')) from $parent.$user)

SQL order by list

Here is part of code for favourited wallpapers:
...
$profile = mysql_fetch_array(mysql_query("SELECT * FROM users WHERE id = $id"));
}
if ($profile['favourites'] != '') {
$from = (($page * $template['fav_wallpaper_limit']) - $template['fav_wallpaper_limit']);
$favourites = substr($profile['favourites'], 2);
/// Tried to join 2 tables, but favourites still displayed by wallpaper id
$sql = mysql_query("
SELECT
*
FROM
wallpapers AS w
JOIN favourites AS f on f.wallpaper_id = w.id
WHERE
w.id IN ($favourites) AND w.published = 1
ORDER BY
f.wallpaper_id LIMIT $from, $template[fav_wallpaper_limit]");
");
Problem is, that it displays wallpapers by the id column that is stored in wallpapers table. While I need to display them by how they wore favourited. The data is stored in users table, and have column favourites for each user with id list of favourited wallpapers.
EXAMPLE:
, 90, 2031, 1, 34, 460, 432, ..., 2013;
Is there any way do grab this tada and order favourites from it?
I think you need to do this within your PHP code:
Read the value of the favourites column;
Explode it into an array;
Iterate through the array, querying the database to get the favourites in the specified order.
The usual way to do this kind of thing is to have a seperate table, say user_favourites with a row for each fovourite for each user that just includes the user id and the favourite id - in this case, with an order factor as well. With the database set up this way, your can execute a query on the new user_favourites table, where user_id is the user id, ordered by the "order factor" to get the favourites in the right order all in one go.
Which database are you using? You might be able to do something like
SELECT _whatever_
FROM favourites
WHERE favourite_id IN (SELECT favourites FROM users)
and it might return the favourites in the correct order. I think the additional table approach is superior, if you can do it that way.

SQL Latest photos from contacts (grouped by contact)

To short version of this question is that I want to accomplish something along the lines of what's visible on Flickr's homepage once you're logged in. It shows the three latest photos of each of your friends sorted by date but grouped by friend.
Here's a longer explanation: For example I have 3 friends: John, George and Andrea. The list I want to extract should look like this:
George
Photo - 2010-05-18
Photo - 2010-05-18
Photo - 2010-05-12
John
Photo - 2010-05-17
Photo - 2010-05-14
Photo - 2010-05-12
Andrea
Photo - 2010-05-15
Photo - 2010-05-15
Photo - 2010-05-15
Friend with most recent photo uploaded is on top but his or her 2 next files follow.
I'd like to do this from MySQL, and for the time being I got here:
SELECT photos.user_id, photos.id, photos.date_uploaded
FROM photos
WHERE photos.user_id IN (SELECT user2_id
FROM user_relations
WHERE user1_id = 8)
ORDER BY date_uploaded DESC
Where user1_id = 8 is the currently logged in user and user2_id are the ids of friends. This query indeed returns the latest files uploaded by the contacts of the user with id = 8 sorted by date. However I'd like to accomplish the grouping and limiting mentioned above.
Hopefully this makes sense. Thank you in advance.
Sometimes, the only way to acheive an end is to create a piece of SQL so ugly and heinous, that the alternative of doing multiple queries becomes attractive :-)
I would just do one query to get a list of your friends then, for each friend, get the three most recent photos. Something like:
friend_list = sqlexec "select user2_id from relations where user1_id = "
+ current_user_id
photolist = []
for friend in friend_list:
photolist += sqlexec "select user_id, id, date_uploaded from photos"
+ " where user_id = "
+ friend.get("user2_id")
+ " order by date_uploaded desc fetch first 3 rows only"
# Now do something with photolist
You don't have to do it as one query any more than you're limited to one regular expression for matching a heinous pattern. Sure it'd be nice to be "clever" but it's rarely necessary. I prefer a pragmatic approach.

Django DB API equivalent of a somewhat complex SQL query

I'm new to Django and still having some problems about simple queries.
Let's assume that I'm writting an email application. This is the Mail
model:
class Mail(models.Model):
to = models.ForeignKey(User, related_name = "to")
sender = models.ForeignKey(User, related_name = "sender")
subject = models.CharField()
conversation_id = models.IntegerField()
read = models.BooleanField()
message = models.TextField()
sent_time = models.DateTimeField(auto_now_add = True)
Each mail has conversation_id which identifies a set of email messages
which are written and replyed. Now, for listing emails in inbox, I
would like as gmail to show only last email per conversation.
I have the SQL equivalent which does the job, but how to construct native Django query for this?
select
*
from
main_intermail
where
id in
(select
max(id)
from
main_intermail
group by conversation_id);
Thank you in advance!
Does this work? It would require Django 1.1.
from django.db.models import Max
mail_list = Mail.objects.values('conversation_id').annotate(Max('id'))
conversation_id_list = mail_list.values_list('id__max',flat=True)
conversation_list = Mail.objects.filter(id__in=conversation_id_list)
So, given a conversation_id you want to retrieve the related record which has the highest id. To do this use order_by to sort the results in descending order (because you want the highest id to come first), and then use array syntax to get the first item, which will be the item with the highest id.
# Get latest message for conversation #42
Mail.objects.filter(conversation_id__exact=42).order_by('-id')[0]
However, this differs from your SQL query. Your query appears to provide the latest message from every conversation. This provides the latest message from one specific conversation. You could always do one query to get the list of conversations for that user, and then follow up with multiple queries to get the latest message from each conversation.