issue with joins and not exist values - php

Here is my table looks..
Users
Id name height weight
1 aaa 1 10
2 bbb 4 104
3 ccc 1 10
4 ddd 56 150
5 eee 232 180
second table looks like
Profile view
Id sender receiver block
1 1 2 True
2 2 3 False
3 4 1 False
The problem i am facing is,,When I search using height and weight in users table and block using profileview table.I couldn't get proper results..
If second user bbb search with height "1" and weight "10" it should be appear 3rd user details ccc .First user also matched but First user blocked second user.The problem is when i using join values coming if sender and receiver exists i the profileview table.If not exist how do we do in joins..

CREATE TABLE #Users
(
Id int,
[Name] varchar(255),
Height int,
[Weight] int
)
CREATE TABLE #ProfileView
(
Id int,
Sender int,
Receiver int,
[Block] varchar(5)
)
INSERT INTO #Users
(Id, [Name], Height, [Weight])
VALUES
(1, 'aaa', 1, 10),
(2, 'bbb', 4, 104),
(3, 'ccc', 1, 10),
(4, 'ddd', 56, 150),
(5, 'eee', 232, 180)
INSERT INTO #ProfileView
(Id, Sender, Receiver, [Block])
VALUES
(1, 1, 2, 'True'),
(2, 2, 3, 'False'),
(3, 4, 1, 'False')
DECLARE
#CallingUser int, --User performing the search
#Height int, --Height searched for
#Weight int --Weight searched for
SET #CallingUser = 2
SET #Height = 1
SET #Weight = 10
SELECT
*
FROM
#Users
LEFT OUTER JOIN #ProfileView
ON #Users.Id = #ProfileView.Id
AND #ProfileView.Receiver = #CallingUser
WHERE
#Users.Id <> #CallingUser
AND #Users.Height = #Height
AND #Users.[Weight] = #Weight
AND (#ProfileView.[Block] = 'False' OR #ProfileView.[Block] IS NULL)
DROP TABLE #Users
DROP TABLE #ProfileView

Related

Copy hierarchical SQL Data in same Table with updated Values

I have a table "projects" and a table "tasks" with hierarchical data in my SQL Database. So the tasks have subtasks which are linked with a "parent"-column to its parentID. The Root-Task-Parent is 0.
There is also a column "project_id" which refers the task to a specific project in the Project-Table. What i want to do now is to copy a whole task with all subtasks and refer it to a new project.
So the SQL-Query would be
INSERT INTO tasks (text, date, parent, projectid)
SELECT text, date, parent, 89
FROM tasks WHERE projectid = 23
where 23 is the id of the old project and 89 is the project to which the data is added.
But the problem is that it keeps the parent value, so my root task is copied properly, but the subtasks still refer to the old tasks. How can i update the parentID as well so the whole tasks and subtasks refer to the new Root Task?
I want to use this in my PHP-Web-Application for a Project-Management-Tool, so that the User can simply choose a "Master-Template" to copy its structure to a new project.
Thank you for your help!
Edit:
#Strawberry: I use dhtmlxgantt to create and update task but i want to solve it with SQL queries. An example Table would look like this:
Screenshot of Database
So in this case i would like to duplicate "Project" to "Project 2" with a new projectID and matching subtasks with parentIDs
I assume that [text] field is unique for each project.
With this assumption, here is my query
--DROP TABLE [Tasks]
-- Create table
CREATE TABLE [dbo].[Tasks](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[Text] [varchar](10) NOT NULL, -- Assume that [Text] field is unique for each project
[Name] [varchar](50) NOT NULL,
[ParentId] [bigint] NULL,
[ProjectId] [bigint] NOT NULL,
CONSTRAINT [PK_Tasks] PRIMARY KEY CLUSTERED
(
[Id] ASC
)
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[Tasks] WITH CHECK ADD CONSTRAINT [FK_Tasks_Tasks] FOREIGN KEY([ParentId])
REFERENCES [dbo].[Tasks] ([Id])
GO
-- Remove all the data from the table and reseed the identity value
DELETE FROM [Tasks]
DBCC CHECKIDENT ('Tasks', RESEED, 1)
-- Sample Data population starts here...
INSERT INTO [Tasks] (text, Name, [ParentId], ProjectId)
SELECT 'A', 'A', null, 101 union ALL
SELECT 'B', 'B', null, 101 union ALL
SELECT 'C', 'C', null, 101
INSERT INTO [Tasks] (text, Name, [ParentId], ProjectId)
SELECT 'A1', 'A 1', (SELECT [Id] FROM [Tasks] WHERE [Text] = 'A'), 101 union ALL
SELECT 'A2', 'A 2', (SELECT [Id] FROM [Tasks] WHERE [Text] = 'A'), 101 union ALL
SELECT 'A3', 'A 3', (SELECT [Id] FROM [Tasks] WHERE [Text] = 'A'), 101 union ALL
SELECT 'A4', 'A 4', (SELECT [Id] FROM [Tasks] WHERE [Text] = 'A'), 101 union ALL
SELECT 'B1', 'B 1', (SELECT [Id] FROM [Tasks] WHERE [Text] = 'B'), 101 union ALL
SELECT 'B2', 'B 2', (SELECT [Id] FROM [Tasks] WHERE [Text] = 'B'), 101 union ALL
SELECT 'B3', 'B 3', (SELECT [Id] FROM [Tasks] WHERE [Text] = 'B'), 101 union ALL
SELECT 'C1', 'C 1', (SELECT [Id] FROM [Tasks] WHERE [Text] = 'C'), 101 union ALL
SELECT 'C2', 'C 2', (SELECT [Id] FROM [Tasks] WHERE [Text] = 'C'), 101 union ALL
SELECT 'C3', 'C 3', (SELECT [Id] FROM [Tasks] WHERE [Text] = 'C'), 101
INSERT INTO [Tasks] (text, Name, [ParentId], ProjectId)
SELECT 'A11', 'A 11', (SELECT [Id] FROM [Tasks] WHERE [Text] = 'A 1'), 101 union ALL
SELECT 'A41', 'A 41', (SELECT [Id] FROM [Tasks] WHERE [Text] = 'A 4'), 101
-- Sample Data population ends here...
GO
-- Copy all the data from project 101 and insert it as 102 with parent id as null
INSERT INTO [Tasks] (text, Name, [ParentId], ProjectId) -- other column names can be here...
SELECT text, Name, null, 102 -- Other column values can be here...
FROM [Tasks] where ProjectId = 101
-- Update the parent id using the text field
UPDATE A
SET A.[ParentId] = C.NewParentId
FROM [Tasks] A
INNER JOIN (SELECT Child.text, Parent.[Text] Parenttext
FROM [Tasks] Child
INNER JOIN [Tasks] Parent
ON Child.[ParentId] = Parent.[Id]
WHERE Child.ProjectId = 101
) B
ON A.[Text] = B.[Text]
LEFT JOIN (
SELECT [Id] NewParentId, [Text]
FROM [Tasks]
WHERE ProjectId = 102
) C
ON B.Parenttext = C.text
WHERE ProjectId = 102
SELECT * FROM [Tasks] WHERE ProjectId = 102 Order By [Text]
I hope this may help you

MySQL query to get sum of differences between column and AVG of same column

I have a table which contains the scores by user, for a game:
UserID (Integer)
MatchId (Integer)
Score (Double)
I'd like to getter sum each user's "points above average" (PAA) - the
amount by which a user's score was above or below the average.
So you'd need to calculate the average of 'Score' for each 'MatchId',
then for each row in the table calculate the amount by which the
'Score' differs from the match average. And then sum that PAA value by
user.
Is it possible to do this via a MySQL query? Or do I need PHP? If it can be done by query, what would that query look like?
plan
compute avg scores by match
join user scores to avg scores and compute sum of derived difference field by userid
setup
create table scores
(
UserID integer not null,
MatchId integer not null,
Score decimal(5, 2) not null,
primary key ( UserID, MatchId )
);
insert into scores
( UserID, MatchId, Score )
values
( 1, 1, 22.1 ),
( 2, 1, 36.0 ),
( 3, 1, 35.3 ),
( 1, 2, 50.0 ),
( 2, 2, 39.8 ),
( 3, 2, 42.0 )
;
query
select s.UserID, sum(s.Score - avgs.avg_score) as paa
from scores s
inner join
(
select MatchId, avg(Score) as avg_score
from scores
group by MatchId
) avgs
on s.MatchId = avgs.MatchId
group by s.UserID
;
output
+--------+-----------+
| UserID | paa |
+--------+-----------+
| 1 | -2.966666 |
| 2 | 0.733334 |
| 3 | 2.233334 |
+--------+-----------+
sqlfiddle

SQL trying to make a ranking column based on age group out of age column

so i have this table
CREATE TABLE RaceResult(name char, time int, age int);
INSERT INTO RaceResult (name, time, age) VALUES
('Steve', '12', '33'),
('Tim', '34', '28'),
('Mark', '22', '37'),
('Tom', '21', '30'),
('Cliff', '13', '33'),
('Vini', '17', '28'),
('Matt', '10', '28'),
('Ben', '9', '29'),
('Brandon', '15', '14');
and i want to create a 4th column that it ranks them 1st 2nd 3rd etc based on their age group
The age groups are
0 - 15 yrs
16 - 29 yrs
30+ yrs
my select statement so far is:
SELECT
CASE
WHEN age < '16' and age > 0
THEN 'group1'
WHEN age < '30' and age > 15
THEN 'group2'
WHEN age > '29'
THEN 'group3'
ELSE 0
END as rank, *
FROM RaceResult
ORDER BY time
but instead of the rank column to just say 'group 1, 2 or 3' i want it to output like:
RESULTS
Name Time Age Rank
===== ==== === ====
Ben 9 29 1
Matt 10 28 2
Steve 12 33 1
Cliff 13 33 2
Brandon 15 14 1
Vini 17 28 3
Tom 21 30 3
Mark 22 37 4
Tim 34 28 4
really appreciate if anyone could point me in the right direction
Try this.
;WITH cte
AS (SELECT NAME,
time,
age,
CASE
WHEN ( age / 15 ) + 1 < 3 THEN ( age / 15 ) + 1
ELSE 3
END AS [group]
FROM RaceResult)
SELECT NAME,time,age,
Row_number() OVER (partition BY [group] ORDER BY time ) [Rank]
FROM cte
ORDER BY time
This query should do what you want:
SELECT
age_group.*,
#num := if (#age_group = age_group, #num + 1, 1) rank,
#age_group := age_group as dummy
FROM (
SELECT
RaceResult.*,
#group := CASE
WHEN age < '16' and age > 0
THEN 'group1'
WHEN age < '30' and age > 15
THEN 'group2'
WHEN age > '29'
THEN 'group3'
ELSE 0
END as age_group
FROM RaceResult,
(select #age_group = '', #num = 1) init
ORDER BY age_group, time
) age_group
The solution is based on info from this link:
http://www.xaprb.com/blog/2006/12/02/how-to-number-rows-in-mysql/

Select subjects from table

I have a table called Grades and inside I have some columns:
Id id_student Subjects grade
3 1 [->] Biology 8
4 1 [->] Math 4
5 1 [->] Sports 4
6 1 [->] Math 8
7 1 [->] English 9
8 4 [->] Sports 10
9 4 [->] English 7
I selected everything from this table where id_student = student logged in
$sth = $this->dbh->prepare("SELECT * FROM note WHERE id_elev = :id_elev");
$sth->bindParam(":id_elev", $_SESSION['id']);
$sth->execute();
$result = $sth->fetch(PDO::FETCH_ASSOC);
So all I selected is this:
Id id_student Subjects grade
3 1 [->] Biology 8
4 1 [->] Math 4
5 1 [->] Sports 4
6 1 [->] Math 8
7 1 [->] English 9
I want to make a average grade for Math , Biology , etc for this student but I want it without making a SELECT * FROM Grades WHERE $result['Subjects'] == 'Biology' because some students may not have this subject in their schedule.
I want something like this:
Id id_student Subjects grade
4 1 [->] Math 4
6 1 [->] Math 8
But without WHERE $results['Subjects'] == 'Math';
I'm sorry it is hard to explain when you don't know a lot of english. I hope that someone understands what I wrote and give me an advice. I can make another table called Subject if it is necessary.
Check out this fiddle:
http://sqlfiddle.com/#!2/8ee5a/3
I think it does what you need. If not, it's a great place to test the query.
I used the GROUP BY function AVG() to get the average grade for each subject.
http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_avg
Here is the schema and query:
CREATE TABLE grades
(
Id int auto_increment primary key,
id_student int,
Subjects varchar(20),
grade int(1)
);
INSERT INTO grades
(Id, id_student, Subjects, grade)
VALUES
('3', '1', 'Biology', 8),
('4', '1', 'Math', 4),
('5', '1', 'Sports', 4),
('6', '1', 'Math', 8),
('7', '1', 'English', 9);
SELECT id_student, Subjects, AVG(grade) FROM grades GROUP BY Subjects;
The query below is an example of the use I mentioned in my comment
-- The AVG() function returns the average value of a numeric column.
-- because you are executing an aggregate function on the Grade column you have to specify which columns to group the results together by.
SELECT
Id
,Subject
,AVG(Grade) as 'Average Grade'
FROM
Result
GROUP BY
Id
,Subject

Seasonal Pricing for an Entity.

I am trying to manage seasonal prices for hotel rooms.
The only way that I can think of doing it would be to use:
A = Room Rate
B = Service Charge for room
Imagine that the table has a roomId column which is omited from below.
| DayDate |EndDate | A | B
-----------------------------------------------
| 2010/07/1 |2010/07/2 | 200 | 40
| 2010/07/3 |2010/07/4 | 150 | 40
| 2010/07/5 |2010/07/5 | 150 | 50
| 2010/07/6 |2010/07/7 | 200 | 50
| 2010/07/8 |2010/07/9 | 100 | 60
etc.. (table taken from another question).
The problem is: I don't want my seasons to be year specific.
Seasons for rooms shouldn't change year on year. I don't want my users to have to enter the seasonal information several times.
I am also going to have thousands of rooms, so I don't know a way to make this easily manageable.
I'm using mysql and php.
Start with a season table that defines the date ranges for the seasons. It should have a primary key field, say season_id. Then have another table to store room, price and season_id. The season_id is a foreign key to the season table.
Create Table Prices
(
MonthStart int not null
, DayStart int not null
, MonthEnd int not null
, DayEnd int not null
, A int not null
, B int not null
)
Insert Prices( MonthStart, DayStart, MonthEnd, DayEnd, A, B )
Select 7, 1, 7, 2, 200, 40
Union All Select 7, 3, 7, 4, 150, 40
Union All Select 7, 5, 7, 5, 150, 50
Union All Select 7, 6, 7, 7, 200, 50
Union All Select 7, 8, 7, 9, 100, 60
It should be noted that this approach presumes that the boundaries of the seasons are specific to the month and day regardless of year or circumstance. In addition, you'll have to decide how to handle leap year. Another approach which might be simpler is to simply enumerate every day of the year:
Create Table Prices
(
MonthStart int not null
, DayStart int not null
, A int not null
, B int not null
, Constraint PK_Prices Primary Key ( MonthStart, DayStart )
)
Insert Prices( MonthStart, DayStart, A, B )
Select 7, 1, 200, 40
Union All Select 7, 2, 200, 40
Union All Select 7, 3, 150, 40
Union All Select 7, 4, 150, 40
Union All Select 7, 5, 150, 50
Union All Select 7, 6, 200, 50
Union All Select 7, 7, 200, 50
Union All Select 7, 8, 100, 60
Union All Select 7, 9, 100, 60

Categories