Best approach for adding timestamp to return most popular rows

Looking good @r937 :sunglasses:

Iā€™ve done as suggested from #17 everything seems to be working ok, no breakdowns. And the hits table is also setup with two columns venue_id and dtstamp both index and PK.

then you can create the hits table as i outlined before, with venue_id as FK to id

Do you mean add the FK onto venue_id inside the new hits table, which is also the PK?
Is the hits table acting as the child table to venues table?

Or do I need to put the FK on id inside the venues table?


Iā€™ve also realised that all my tables are using MyISAM I understand FKs can only be used on InnoDB.

The new hits table is InnoDB, my question, will the venues table break, cause any issues if I change from MyISAM to InnoDB which has lots of live data and queries?

Does sql act differently when using different storage engines? Meaning do I need to write the queries/code in a different way

Barry

just to confirm what you mean by ā€œindex and PKā€ could you please do a SHOW CREATE TABLE

the most effective way i can think of to answer this question is to give you two hints:

  1. FK always work in one direction only, from the dependent table to the table it references. In other words, one table, often called the parent, acts as the repository of valid values, and the other table, often called the child, is not allowed to have any values in it that cannot be referenced in the parent table

  2. after i said ā€œwith venue_id as FK to idā€, which direction do you think i meant?

fortunately, converting the tables is easyā€¦ iā€™ll let you google it

at what time in the past have you ever coded any sql differently because of the target table type?

CREATE TABLE `tbl_venue_hits` (
 `venue_id` int(11) NOT NULL,
 `dtstamp` datetime NOT NULL,
 PRIMARY KEY (`venue_id`,`dtstamp`),
 KEY `dtstamp` (`dtstamp`,`venue_id`),
 CONSTRAINT `tbl_venue_hits_ibfk_1` FOREIGN KEY (`venue_id`) REFERENCES `tbl_venues_innodb` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

Iā€™ve added a FK as test also, based on my assumptions :slight_smile:

Venue to hits table
Hits table is the child and should have the FK?

If correct, I just read columns with FK can not be unique, venue_id inside hits is PK and unique, no?

fortunately, converting the tables is easyā€¦ iā€™ll let you google it

Yes I have done that ha cheers, easy than I thought :sunglasses:

at what time in the past have you ever coded any sql differently because of the target table type?

I havenā€™t ha. Ok - good learning exercise, thank you.

Barry

Once we move forward @r937

I was previously using the below to update the hits column on my venues table:

$mysqli->query("UPDATE tbl_venues
  SET hits = hits + 1
  WHERE venue_id='" . str_replace("-", " ", strtolower($_GET['venue_id'])) . "'");

Iā€™ll now need to update the hits_table to accomplish the same functionality, how should I change this now, is this an easy fix?

Barry

you can keep doing that if you wish

however, you also need to insert a row for each hit into the venue_hits table

Ok nearly complete @r937 :slight_smile:

A couple of important questions so I can bring this to a close.

  1. Is SHOW CREATE TABLE snippet in my reply in #23 correct?
  2. As mentioned about the hits venue_id which is unique PK also FK to venues table. Is this correct?

The reason I ask, what I readā€¦

"Foreign keys are almost always ā€œAllow Duplicates,ā€ which would make them unsuitable as a Primary Key.

Instead, find a field that uniquely identifies each record in the table, or add a new field (either an auto-incrementing integer or a GUID) to act as the primary key.

The only exception to this are tables with a one-to-one relationship, where the foreign key and primary key of the linked table are one and the same

After reading these comments, and if we stick with the PK and FK combination in the hits table, that would mean weā€™re using a one-to-one relationship, correct?

And could I use the same combination with a one-to-many relationship?

however, you also need to insert a row for each hit into the venue_hits table

How would the SQL look, little example?

Thanks, Barry

Who ever wrote that should be smacked. A PK does not need to be a autoincrement field or a GUID. They are convenient when youā€™re using it as a FK to another table, but even then, they arenā€™t required. TECHNICALLY, a primary key isnā€™t required, period. Strongly recommended, and required by a lot of entity frameworks, but otherwise not required.

But your venue_id, dtstamp will most likely give you a unique value, so itā€™s fine for a primary key. And it will be, by definition, a one-to-many relationship because you will have multiple entries in tbl_venue_hits for a particular venue_id which ties to tbl_venues.

:joy: Best quote today!

Thats great Dave, thanks for clearing this up. Puts my mind at ease :sunglasses:

Couple of final questions:

  1. So in theory, I can create other FKs from other tables also pointing to the venues table id?
    Reason being, I have a comments table, photo table about the same venue which Iā€™ll be able to connect once I convert my tables to InnoDB.
  2. What is the best way to add a row/hit to my hits table based on the snippet I mention in #24
  3. Since updating my database from MyISAM to InnoDB my row count has now become a minus -49, is the normal?

Cheers, barry

  1. Yes
  2. Rudy already answered that above :wink:
  3. Iā€™m pretty sure having less than a row is impossible

Yes.

If a numeric field isnā€™t UNSIGNED it is possible it could be negative.

So it might be your query is returning a value instead of a count.

Else Iā€™d guess there is an error in you (PHP?) code that is doing subtraction incorrectly.

Yes Ruby did mention though not sure how/correct way to code this?

Simple INSERT as below?

Knowing that one column is timestamp and the other is auto_increment, do I need the values?

mysqli->query("INSERT INTO table_hits (column1,column2)
VALUES (value1,value2)
WHERE venue_id='" . str_replace("-", " ", strtolower($_GET['venue_id'])) . "'");

Barry

Iā€™ve just read:

If you look closely, youā€™ll notice itā€™s not a negative sign, itā€™s a tilde, which means ā€œapproximatelyā€.

InnoDB tables do not store the exact count of rows in the table, so you are being shown approximately how many rows are in the table.

Though looks like a minus.

If a numeric field isnā€™t UNSIGNED it is possible it could be negative.

Should I make it unsigned, this is how it should be setup from the beginning?
And is it ok for FK to be unsigned?

Update
Iā€™ve just made column unsigned, nothing changed.

1 Like

Nope. It needs to be a standard insert (note, this is not the secure way to do it, and Iā€™m too tired to look it upā€¦

mysqli->query("INSERT INTO table_hits (venue_id, dtstamp)
VALUES ('" . str_replace("-", " ", strtolower($_GET['venue_id'])) . "', NOW()");

No worries :slight_smile:
The helps, I have been using prepare stmt which I think will make this more secure.

Thanks, barry

If anybody can help, small error when I run:

INSERT INTO tbl_venue_hits(venue_id, dtstamp) VALUES ('venuename',NOW())

Error

Cannot add or update a child row: a foreign key constraint fails (tbl_venue_hits, CONSTRAINT tbl_venue_hits_ibfk_1 FOREIGN KEY (venue_id) REFERENCES tbl_venues_innodb (id))

Barry

[quote=ā€œcomputerbarry, post:35, topic:242540, full:trueā€]
If anybody can help, small error [/quote]
itā€™s telling you that youā€™re trying to violate the FK constraint

youā€™re trying to add a row with a value for venue_id that doesnā€™t exist in the id column of tbl_venues_innodb

itā€™s doing exactly what you asked it to do ā€“ preventing you from inserting invalild data

:slight_smile:

:smiley:

I did realise this, now we know things are setup correctly - a good protection.

youā€™re trying to add a row with a value for venue_id that doesnā€™t exist in the id column of tbl_venues_innodb

So what is the correct way r937?

Barry

do not insert a row into the hits table for a venue that doesnā€™t exist in the venues table

do not insert a row into the hits table for a venue that doesnā€™t exist in the venues table

But thats the thing r937ā€¦ ā€˜venuenameā€™ is a row inside the venues table, itā€™s the venue_id of a venue, I just change it here to venuename for example.

What have I missed?

Barry

Ok, Iā€™ve just added:

INSERT INTO tbl_venue_hits(venue_id, dtstamp) VALUES (1,now())

Which worked.

I now have one row inside the hits table:

venue_id : 1
dtstamp: 2016-11-09 22:38:51

How am I suppose to link this to the venue_id inside venues?
This could be anything.

How do I relate and pass the correct venue_id whith this?

Very confusing @r937